2

为什么我需要更改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

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

4

1 回答 1

5

comp.lang.c FAQ对此有一个问题,总结如下:

不能char **const char ** 指针赋值的原因有些晦涩。鉴于const限定符完全存在,编译器希望帮助您遵守不修改const值的承诺。这就是为什么您可以将 a 分配char *给 a const char *,但不能反过来:将“添加”-ness 到一个简单的指针显然是安全的 const,但将其拿走会很危险......在 C 中,如果您必须分配或传递在第一级间接之外具有限定符不匹配的指针,您必须使用显式强制转换

这是它给出的例子,第 3 行应该给出警告:

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

第 1 行和第 2 行显然没问题。在第 4 行,&c有 type pointer to const char,并且因为char **是 type pointer to pointer to const char, then*p2也是 type pointer to const char,所以语句很好。第 5 行也可以,因为p1是 type pointer to char,所以你可以修改它指向的内容。

因此,如果第 3 行没问题,那么您最终会完全按照您希望const阻止您做的事情来修改chara 指向的内容pointer to pointer to const char,因此第 3 行是不允许的,并且您不能在没有强制转换的情况下分配char **给 a const char **

请注意,添加演员表只是隐藏了问题,并不能解决问题。如果您添加演员表,上面的第 3 行将起作用,并且您可以间接修改明显的const char. 虽然这并不总是正确的,但这是一个很好的例子,说明屈服于 C 的明显需要通常只是一个错误。

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

于 2013-10-18T02:48:21.660 回答