C数组的数组:为什么我需要在这里转换TO const?

时间:2013-10-18 02:34:45

标签: c arrays const

为什么我需要将此代码中的print_args调用更改为print_args(argc, (const char**)argv)以使其编译?

#include <stdio.h>

void print_args(int argc, const char *argv[]) {
    for (int i = 0; i < argc; ++ i) {
        puts(argv[i]);
    }
}

int main(int argc, char *argv[]) {
    print_args(argc, argv);
    return 0;
}

当我使用gcc编译它时,我收到此错误:

$ gcc -Werror -std=c99 -g const.c -o const
const.c: In function ‘main’:
const.c:10:2: error: passing argument 2 of ‘print_args’ from incompatible pointer type [-Werror]
const.c:3:6: note: expected ‘const char **’ but argument is of type ‘char **’
cc1: all warnings being treated as errors

(请注意,这只是一个简化的示例代码来说明问题。)

1 个答案:

答案 0 :(得分:4)

comp.lang.c常见问题has a question on this,总结:

  

您无法为char **分配const char **值的原因   指针有点模糊。鉴于const限定符存在于   所有,编译器都希望帮助您兑现承诺   修改const值。这就是为什么你可以将char *分配给const char *,而不是另一种方式:“添加”显然是安全的   const - 指向一个简单的指针,但接受它会很危险   在...中,如果必须指定或传递具有限定符的指针   您必须使用除第一级间接之外的不匹配   显式演员

以下是它给出的示例,其中第3行应该发出警告:

const char c = 'x';         /* 1 */
char *p1;                   /* 2 */
const char **p2 = &p1;      /* 3 */
*p2 = &c;                   /* 4 */
*p1 = 'X';                  /* 5 */

第1行和第2行显然很好。在第4行,&c的类型为pointer to const char,由于char **的类型为pointer to pointer to const char,因此*p2的类型为pointer to const char,因此声明很好。第5行也没问题,因为p1pointer to char类型,因此您可以修改它指向的内容。

因此,如果第3行是正常的,那么您最终会完全按照预期const执行操作,以防止您执行操作,修改char所指向的pointer to pointer to const char,因此第3行是允许,如果没有演员,您无法将char **分配给const char **

请注意,添加强制转换只会隐藏问题,但不会修复它。如果添加了强制转换,上面的第3行就可以工作了,你可以间接地修改const char。虽然并非总是如此,但这是一个很好的例子,表明在C语言中显然需要投射通常只是一个错误。

请注意,在C ++中,您可以声明函数参数const char * const * argv,它可以在没有强制转换的情况下工作,并防止间接修改。