C数组数组:为什么我需要在此处强制转换为const?

pan*_*nzi 2 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;
}
Run Code Online (Sandbox Code Playgroud)

当我用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
Run Code Online (Sandbox Code Playgroud)

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

Cro*_*man 5

comp.lang.c常见问题对此有一个问题,总结为:

无法char **const char ** 指针分配值的原因有些模糊。考虑到const限定词的存在,编译器希望帮助您信守承诺,不要修改const值。这就是为什么您可以将a分配char *给a const char *,而不是相反:将“ const- ”添加到简单指针显然很安全,但是将其删除 很危险...在C中,如果必须分配或传递在第一个间接级别之外具有限定符不匹配的指针,则必须使用显式强制转换

这是它给出的示例,其中第3行应给出警告:

const char c = 'x';         /* 1 */
char *p1;                   /* 2 */
const char **p2 = &p1;      /* 3 */
*p2 = &c;                   /* 4 */
*p1 = 'X';                  /* 5 */
Run Code Online (Sandbox Code Playgroud)

第一行和第二行显然很好。在第4行,&c有型pointer to const char,而且由于char **是类型pointer to pointer to const char,那么*p2也是类型pointer to const char,所以声明是好的。第5行也很好,因为它p1是type pointer to char,所以您可以修改它指向的内容。

所以,如果第3行是行,那么你最终究竟做你所期望的const,以防止你做,修改char指向的一个pointer to pointer to const char,所以第3行是容许的,你不能分配char **const char **没有投。

请注意,强制转换只是隐藏了问题,并不能解决问题。如果您添加了强制转换,则上面的第3行将可以正常工作,并且您可以间接地修改表观const char。尽管并非总是如此,但这是一个很好的例子,表明屈从于明显的强制转换C常常只是一个错误。

请注意,在C ++中,您可以声明函数参数,const char * const * argv并且该函数参数无需强制转换即可工作,并可以防止间接修改。