当前位置: 动力学知识库 > 问答 > 编程问答 >

C arrays of arrays: why do I need to cast TO const here?

问题描述:

Why do I need to change the print_args call in this code to print_args(argc, (const char**)argv) to make it compile?

#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;

}

When I compile it with gcc I get this error:

$ 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

(Note that this is just a simplified example code to illustrate the problem.)

网友答案:

The comp.lang.c FAQ has a question on this, summarizing:

The reason that you cannot assign a char ** value to a const char ** pointer is somewhat obscure. Given that the const qualifier exists at all, the compiler would like to help you keep your promises not to modify const values. That's why you can assign a char * to a const char *, but not the other way around: it's clearly safe to "add" const-ness to a simple pointer, but it would be dangerous to take it away...In C, if you must assign or pass pointers which have qualifier mismatches at other than the first level of indirection, you must use explicit casts

Here's the example it gives, where line 3 should give a warning:

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

Lines 1 and 2 are obviously fine. On line 4, &c has type pointer to const char, and since char ** is type pointer to pointer to const char, then *p2 is also of type pointer to const char, so the statement is fine. Line 5 is also fine, because p1 is type pointer to char, so you can modify what it points to.

So if line 3 is OK, then you end up doing exactly what you expect const to prevent you from doing, modifying the char pointed to by a pointer to pointer to const char, so line 3 is not allowed, and you can't assign char ** to a const char ** without a cast.

Note that putting the cast in merely hides the problem, it doesn't fix it. Line 3 above would work if you added the cast, and you'd be able to indirectly modify an apparently const char. While it's not always true, this is a good example of where succumbing to an apparent need to cast in C is often just a mistake.

Note that in C++, you could declare your function parameter const char * const * argv and it would work without a cast, and prevent the indirect modification.

分享给朋友:
您可能感兴趣的文章:
随机阅读: