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

C中的双指针常量正确性警告,c,constants,implicit-conversion,qualifiers,multiple-indirection,C,Constants,Implicit Conversion,Qualifiers,Multiple Indirection,指向非常量数据的指针可以隐式转换为指向相同类型常量数据的指针: int *x = NULL; int const *y = x; 添加额外的常量限定符以匹配额外的间接寻址在逻辑上应以相同的方式工作: int * *x = NULL; int *const *y = x; /* okay */ int const *const *z = y; /* warning */ 但是,使用GCC或使用-Wall标志编译此文件会导致以下警告: test.c:

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

int       *x = NULL;
int const *y = x;
添加额外的常量限定符以匹配额外的间接寻址在逻辑上应以相同的方式工作:

int       *      *x = NULL;
int       *const *y = x; /* okay */
int const *const *z = y; /* warning */
但是,使用GCC或使用
-Wall
标志编译此文件会导致以下警告:

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
限定符“放弃嵌套指针类型中的限定符”

为什么
const
只能添加一个级别深的限定符,这一点很微妙,可以用以下公式来解释

简要地考虑一下这个与你的密切相关的例子:

const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */
C通过只允许赋值在指向级别的第一个位置丢弃限定符来避免此问题(因此不允许在此处赋值到
z


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

< P>为什么代码> const <代码>只能添加一个深度是很微妙的,并用.< /p>解释。

简要地考虑一下这个与你的密切相关的例子:

const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */
C通过只允许赋值在指向级别的第一个位置丢弃限定符来避免此问题(因此不允许在此处赋值到
z


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

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

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

事实上,后一种代码在概念上没有什么问题。这只是C规范中不允许的一个缺陷,它迫使C程序员在代码中包含难看的类型转换


< C可能使用C++所做的相同规则;但是,C标准委员会没有决定这样做。

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

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

事实上,后一种代码在概念上没有什么问题。这只是C规范中不允许的一个缺陷,它迫使C程序员在代码中包含难看的类型转换


< C可能使用C++所做的相同规则;然而,C标准委员会没有决定这样做。

术语的一个小问题:强制转换是一种明确的转换。这里所做的是隐式转换,而不是cast.ITYM指针指向const指针指向const('const pointer'可能不明确)。如果
x->y->z
(其中
->
仅表示“指向”,而不是取消引用运算符),则可以更改内容
z
,而无需更改
y
。因此,如果它指向非const的const指针,则可以改变值<代码> z <代码>,而不改变<代码> y>代码>这不是C++中常见问题的解释吗?@杰夫,FAQ指出,将<代码> Fo**<代码> > <代码> Fo-const * const */COD>我不太明白这怎么不适用于这里。但听起来这是相关的。如果你愿意把它作为一个答案,你会得到我的选票。@杰夫M: C和C++规则的正确性是不同的,这个问题是关于C的小术语:一个演员是一个明确的转换。这里所做的是隐式转换,而不是cast.ITYM指针指向const指针指向const('const pointer'可能不明确)。如果
x->y->z
(其中
->
仅表示“指向”,而不是取消引用运算符),则可以更改内容
z
,而无需更改
y
。因此,如果它指向非const的const指针,则可以改变值<代码> z <代码>,而不改变<代码> y>代码>这不是C++中常见问题的解释吗?@杰夫,FAQ指出,将<代码> Fo**<代码> > <代码> Fo-const * const */COD>我不太明白这怎么不适用于这里。但听起来这是相关的。如果你愿意把它作为答案,你会得到我的选票。@杰夫M: C和C++规则的正确性是不同的,这个问题是关于C.@ CAF-我想知道为什么这是在发出警告!猜测C++规则确实允许这个转换。感谢信息链接。以前我在C++中只广泛使用了 const ,所以行为上的差异是相当惊人的。链接现在被打破了。猜测C++规则确实允许这个转换。感谢信息链接。以前我在C++中只广泛使用了 const ,所以行为上的差异是相当惊人的。