【问题标题】:Double pointer const-correctness warnings in CC中的双指针常量正确性警告
【发布时间】:2011-06-30 15:37:28
【问题描述】:

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

【问题讨论】:

  • 小术语:演员表是一种显式转换。您在这里所做的是隐式转换,而不是强制转换。
  • ITYM 指向 const 的指针 指向 const 的指针(“const 指针”可能不明确)。如果x -> y -> z(其中-> 仅表示“指向”而不是取消引用运算符)您可以更改内容z 而无需更改y。因此,如果它是指向 const 的指针指向非 const 的指针,则可以更改值 z 而无需更改 y
  • 这不只是const correctnessc++ 常见问题解答中解释的一个实例吗?
  • @Jeff 常见问题解答指出可以将Foo ** 转换为Foo const * const *。我不太明白它在这里不适用。但听起来这是相关的。如果您愿意将其发布为答案,您将获得我的投票。
  • @Jeff M:C 和 C++ 关于 const-correctness 的规则是不同的,这个问题是关于 C 的。

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


【解决方案1】:

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 的更简单的规则不会区分您的情况和上面的示例。

【讨论】:

  • @caf- 我想知道为什么这会产生警告!猜猜 C++ 规则确实允许这种转换。
  • 感谢您提供的信息链接。我以前只在 C++ 中广泛使用过const,所以这种行为上的差异是相当令人惊讶的。
  • 链接已断开。
【解决方案2】:

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      相关资源
      最近更新 更多