GCC下“initializing ‘char **’ with an expression of type ‘const char **’ discards qualifiers in nested pointer types”警告解读

我曾经被这个警告困扰了好久好久,问了好些人,都说没遇到过=_=…
问题代码片段(与问题无关的代码块已被忽略):

size_t MyConv(const char *orginStr, const char *targetStr, ...) {
    char **tmpIn = NULL;
    char **tmpOut = NULL;
        ...
        ...
    tmpIn = &orginStr;
    tmpOut = &targetStr;
        ...
        ...
}

GCC编译后会弹出如下警报:

sfind.c:887:8: warning: assigning to 'char **' from 'const char **' discards qualifiers in nested pointer types
      [-Wincompatible-pointer-types-discards-qualifiers]
        tmpIn = &orginStr;
              ^ ~~~~~~~~~

这条警告信息翻译出来是“用类型表达式初始化“char \**” “const char \**”丢弃嵌套指针类型中的限定符。 ”,个人表示很晦涩难懂。。。
后来翻阅《C专家编程》的时候,偶然间发现一个章节是讨论const限定符的,认真看了下,顿时感慨自己学识太过浅薄。
上面的代码中,实参const char \*orginStr的const是修饰char orginStr的,而char **tmpOut是指向char *类型变量的一个指针(此“char *”类型无修饰符),这两点倒是没有疑惑。但当二者互相赋值的时候,const char *orginStrchar \**tmpOut这两个指针所指向的类型的修饰符不同。一个是const char orginStr,带了const修饰符,而另一个则是char *tmpOut,并没有const修饰符。指针变量赋值时,赋值语句左边的指针所指向的类型必须具有赋值语句右边的类型所拥有的全部修饰符,才能正常通过编译,否则就会舍弃右边变量多余的修饰符。

以下内容摘自ANSI C标准手册

两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。

也就是说:

int *a = NULL;
const int *b = a;

上面这段代码是可以正常通过编译的,因为赋值语句左边的指针指向的数据类型拥有了右边的数据类型的所有修饰符(甚至还比右边的多了一个const)而下面这段却不行。

const int *a = NULL;
int b = a;

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha Code