为什么const限定符警告依赖于变量内容,而不是类型?

前端之家收集整理的这篇文章主要介绍了为什么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("%s\n",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的对象.

猜你在找的C&C++相关文章