C中的双指针常量正确性警告

时间:2011-02-20 06:41:51

标签: c const implicit-conversion qualifiers multiple-indirection

指向非const数据的指针可以隐式转换为指向相同类型的const数据的指针:

int       *x = NULL;
int const *y = x;

添加额外的const限定符以匹配额外的间接寻址应该在逻辑上以相同的方式工作:

int       *      *x = NULL;
int       *const *y = x; /* okay */
int const *const *z = y; /* warning */

使用-Wall标志将其与GCC或Clang进行编译,会产生以下警告:

test.c:4:23: warning: initializing 'int const *const *' with an expression of type
      'int *const *' discards qualifiers in nested pointer types
    int const *const *z = y; /* warning */
                      ^   ~

为什么在嵌套指针类型中添加额外的const限定符“丢弃限定符”?

3 个答案:

答案 0 :(得分:46)

const只能添加一个级别的原因是微妙的,并由Question 11.10 in the comp.lang.c FAQ解释。

简而言之,请考虑与您的示例密切相关的示例:

const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */

C通过仅允许在第一个指向级别丢弃限定符来避免此问题(因此不允许在此处分配z)。

您的确切示例不会遇到此问题,因为const第二级意味着无论如何都不会允许分配给*z。在这种情况下,C ++ 允许它,但C的更简单的规则不区分你的情况和上面的例子。

答案 1 :(得分:8)

由另一个答案链接的FAQ条目解释了为什么不允许使用以下代码:

int **x = whatever;
const int **z = x;

但是,您的代码const int *const *z = x;是完全不同的,它不会受到FAQ提出的相同缺陷的影响。

事实上,后一种代码在概念上没有任何问题。它只是C规范中的一个缺陷,它是不允许的,它迫使C程序员在其代码中包含丑陋的强制转换。

C可能会使用与C ++相同的规则;但是C标准委员会并未决定这样做。

答案 2 :(得分:0)

原因,为什么添加限定符的自动化只适用于第一个间接级别,可以从标准中读取:

The Standard 在 6.5.16.1 中声明,“两个操作数都是指向兼容类型的限定或非限定版本的指针,左侧指向的类型具有所有 右侧所指类型的限定符"
句子的最后一部分意味着在指向的类型中添加限定符是没有问题的。
第一部分声称“兼容”类型。并且(我认为)6.7.3 (11) 确实针对限定类型描述了这一点:“要使两个限定类型兼容,两者都应具有兼容类型的相同限定版本。

读到这里,您的指向类型不被认为是兼容的(即使可以将一个分配给另一个)。

因此我会说关于丢弃限定符的clang警告有点误导,但它指的是非相同限定的指向类型。