我想知道是否在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
答案 0 :(得分:3)
指向类型为T的对象的指针被隐含地转换为a 指向const-T类型对象的指针。这是隐式转换吗? 在C11标准中定义的某个地方?
是。这种隐式转换是标准规定的。
第Paragraph 3节包含指针的转换,除了允许的指令 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 子聚合或包含联合的成员,或字符类型。