c - 隐式指针到 Const-T 转换

标签 c constants 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

最佳答案

A pointer to an object of type T is implicitely converted into a pointer to an object of type const-T. Is this implicit conversion somewhere defined in the C11 standard?

是的。这种隐式转换是标准强制要求的。

Paragraph 36.5.4 Cast Operators说的是

Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.

第 3 点下引用的 6.5.16.1 说:

the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

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

const T **pp = &p; 不属于此范围,因此您需要显式强制转换(C++ 允许 const T*const*pp = &p; (需要第二个常量)但 C 仍然不需要。)

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

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

但您需要注意访问/取消引用,这将受 strict aliasing rule 的控制:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)

a type compatible with the effective type of the object, a qualified version of a type compatible with the effective type of the object, a type that is the signed or unsigned type corresponding to the effective type of the object, a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or a character type.

关于c - 隐式指针到 Const-T 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49633108/

相关文章:

c - 为什么这个 if 语句需要括号?

c - 在命令行中使用 Tab 自动完成文本

c++ - 如何包装 C __cdecl API 以便 FORTRAN 可以调用它(使用 __stdcall)?

c++ - 将对象参数作为 const 传递并读取它

c++ - 在 Type 和 Wrapper<Type> 之间 reinterpret_cast 是否安全?

c++ - 使用临时存储区 : is it allowed? 复制可简单复制的类型

c - 如何解析/proc/meminfo

c++ - 如何根据模板参数创建一个方法const?

c++ - 我需要复制构造函数吗?以及如何使用复制构造函数将 const 对象复制到非 const 对象

c++ - 为什么没有 std::on_exit?