61

指向非常量数据的指针可以隐式转换为指向相同类型的 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限定符“丢弃嵌套指针类型中的限定符”?

4

3 回答 3

59

const只能添加一层深度的原因很微妙, comp.lang.c FAQ 中的问题 11.10对此进行了解释。

简而言之,考虑这个与你的例子密切相关的例子:

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

C 通过只允许分配丢弃第一个指向级别的限定符来避免这个问题(因此z不允许分配到这里)。

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

于 2011-02-20T07:21:02.563 回答
12

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

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

但是,您的代码const int *const *z = x;完全不同,它不会受到常见问题解答中提出的相同缺陷的影响。

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

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

于 2015-04-10T03:46:57.520 回答
0

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

标准在 6.5.16.1 中声明对于赋值,“两个操作数都是指向兼容类型的合格或不合格版本的指针,左侧指向的类型具有右侧指向的类型的所有限定符
最后一部分of the sentence 意味着在指向的类型中添加限定符是没有问题的。
第一部分声称“兼容”类型。并且(我认为)6.7.3 (11) 确实为合格类型描述了这一点:“对于两个兼容的合格类型,两者都应具有兼容类型的相同合格版本。

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

Hence I would say that the clang warning about discarding qualifiers is a bit misleading, but it refers to the non-identically qualified pointed-to types.

于 2021-06-21T11:48:00.153 回答