隐式指针到Const-T的转换

时间:2018-04-03 14:53:46

标签: c const language-lawyer

我想知道是否在C11标准中定义了对const数据类型指针的隐式转换:

T x;
const T *p = &x;

指向类型为T的对象的指针被隐式转换为指向类型为const T的对象的指针。这种隐式转换是在C11标准中定义的吗? (我知道允许这个以及它是多么有用是有意义的。我只是想知道它在标准中的定义)

此外,是否根据C11禁止从T**类型到const T**的隐式转换?

T *p;
const T **pp = &p;

这是一个众所周知的问题部分,因此GCC和LLVM / clang会发出警告。我仍然想知道根据C11标准是否允许这样做。我只在§6.5.16.1P6中发现这应该是约束违规的注释。但是,我没有看到应该违反哪个约束。我再次知道这应该被禁止,并且这种隐式转换会导致细微的问题。我只是想知道这是否是根据C11的(未)定义的行为。

同样,我的两个问题不是关于这是否好(这里有多次回答),而是C11标准如何/在何处定义。

为了完整起见,这里有一个链接,说明为什么第二个例子有问题:http://c-faq.com/ansi/constmismatch.html

1 个答案:

答案 0 :(得分:3)

  

指向类型为T的对象的指针被隐含地转换为a   指向const-T类型对象的指针。这是隐式转换吗?   在C11标准中定义的某个地方?

是。这种隐式转换是标准规定的。

Paragraph 3

6.5.4 Cast Operators

  

包含指针的转换,除了允许的指令   6.5.16.1的约束应通过明确的方式规定   铸造。

和第3点下引用的6.5.16.1说:

  

左操作数具有原子,限定或非限定指针类型,   和(考虑左值操作数在左值后的类型   转换)两个操作数都是限定或不合格的指针   兼容类型的版本,以及左侧指向的类型   右边指出的所有类型的限定符;

因此const T *p = &x;的隐式转换成立,因为您只是添加限定符,而不是删除它们。

const T **pp = &p;并不属于这个范畴,所以你需要一个显式的强制转换(C ++允许const T*const*pp = &p;(需要第二个const)但C仍然不会。(<) / p>

只要对齐匹配(对于指向不同限定类型的指针),通过显式强制转换的指针转换就UB而言不是问题,因为 6.3.2.3p7保证:

  

指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   aligned68)对于引用的类型,行为是未定义的。   否则,当再次转换回来时,结果应该相等   到原始指针。当指向对象的指针转换为   指向字符类型的指针,结果指向最低的地址   对象的字节。结果的连续增量,直到   对象的大小,指向剩余字节的指针   对象

但您需要注意由strict aliasing rule管理的访问/解除引用:

  

对象的存储值只能由左值访问   具有以下类型之一的表达式:88)

     

与对象的有效类型兼容的类型,合格   与该对象的有效类型兼容的类型的版本,a   类型是对应的有符号或无符号类型   对象的有效类型,有符号或无符号的类型   类型对应于有效类型的限定版本   对象,包含其中一个的聚合或联合类型   其成员之间的上述类型(包括,递归,a   子聚合或包含联合的成员,或字符类型。