为什么我需要将此代码中的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
(请注意,这只是一个简化的示例代码来说明问题。)
答案 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行也没问题,因为p1
是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
,它可以在没有强制转换的情况下工作,并防止间接修改。