为什么const限定符警告依赖于变量内容,而不是类型?
我从
gcc发现了一个奇怪的行为,代码如下:
#include <stdio.h> #include <string.h> int main(void) { const char str[] = "This string contains é which is a multi-byte character"; const char search[] = "?"; char * pos = strstr(str,search); printf("%sn",pos); return 0; } 编译器会发出警告: $gcc toto.c -std=c99 toto.c: In function ‘main’: toto.c:8:18: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default] 但是,如果我更改搜索内容: const char search[] = "é"; 同样的编译没有任何警告:为什么? 注意:如果我交换Σ和é,我的行为完全相同:如果搜索中的字符不在str中,我会收到警告. 解决方法
它似乎是gcc中的一个错误,在以后的版本中得到纠正.
这是我编写的一个小程序来说明问题. #include <stdio.h> #include <string.h> int main(void) { const char message[] = "hello"; #ifdef ASCII_ONLY const char search_for[] = "h"; #else const char search_for[] = "?"; #endif char *non_const_message = strstr(message,search_for); if (non_const_message == NULL) { puts("non_const_message == NULL"); } else { puts(non_const_message); } } 当我用它编译时 gcc -DASCII_ONLY -std=c99 -pedantic-errors c.c -o c (在Linux Mint 17上使用gcc 4.8.2),它编译时没有诊断消息,并且打印结果程序 hello (我使用-pedantic-errors,因为这会导致gcc(尝试)成为符合标准的ISO C编译器.) 当我删除-DASCII_ONLY选项时,我收到编译时错误消息: c.c: In function ‘main’: c.c:11:31: error: initialization discards ‘const’ qualifier from pointer target type char *non_const_message = strstr(message,search_for); strstr函数返回char *类型的结果,而不是const char *.它需要两个const char *参数,并且使用正确的搜索字符串,它可以返回其第一个参数的值.这意味着它可以静默地丢弃其参数的常量.我认为这是C标准库中的一个缺陷,但我们可能会坚持使用它.如果他们想要保持一致,那么符合C实现就没有选择“修复”这个缺陷;他们可以警告strstr的危险使用,但他们不能拒绝其他合法的代码. (通过将strstr分成两个具有不同名称的函数,可以避免这个缺陷,一个采用const char *并返回一个const char *,另一个采用char *并返回一个char *.1989 ANSI C委员会没有’ t抓住机会这样做,要么是因为他们没有想到它,要么是因为他们不想破坏现有代码.C通过拥有两个重载版本的strstr来解决它,这不是C的可能性.) 我的第一个假设是gcc“神奇地”做了类似于C的事情 – 但是仅使用ASCII字符丢弃const的示例不会导致诊断消息.正如我的测试程序所示,问题是通过在字符串文字中使用非ASCII字符(“Σ”而不是“h”)来触发的. 当我使用gcc 4.9.1(我从源代码安装)而不是gcc 4.8.2(我系统上安装的默认版本)时,问题就消失了: $gcc -DASCII_ONLY -std=c99 -pedantic-errors c.c -o c && ./c hello $gcc -std=c99 -pedantic-errors c.c -o c && ./c c.c: In function ‘main’: c.c:11:31: error: initialization discards ‘const’ qualifier from pointer target type char *non_const_message = strstr(message,search_for); ^ $gcc-4.9.1 -DASCII_ONLY -std=c99 -pedantic-errors c.c -o c && ./c hello $gcc-4.9.1 -std=c99 -pedantic-errors c.c -o c && ./c non_const_message == NULL $ 我没有进一步追踪这个bug,但你可能会在4.8.2和4.9.1之间修复的gcc错误列表中找到它. 对于问题中的代码,您可以通过将pos定义为const char *而不是char *来避免此问题.无论如何它应该是const char *,因为它指向一个被定义为const的对象. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |