将整数转换为指针总是定义良好吗? [英] Is converting an integer to a pointer always well defined?

查看:146
本文介绍了将整数转换为指针总是定义良好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是有效的C ++吗?

Is this valid C++?

int main() {
    int *p;
    p = reinterpret_cast<int*>(42);
}

假设我从未取消引用p.

我们正在寻找C ++标准

Looking up the C++ standard, we have

C ++ 17§6.9.2/3 [basic.compound]

3 指针类型的每个值都是以下值之一:

3 Every value of pointer type is one of the following:

  • 指向对象或函数的指针(据说该指针指向该对象或函数),或者
  • 超出对象末尾的指针([expr.add]),或
  • 该类型的空指针值([conv.ptr]),或
  • 无效的指针值.
  • a pointer to an object or function (the pointer is said to point to the object or function), or
  • a pointer past the end of an object ([expr.add]), or
  • the null pointer value ([conv.ptr]) for that type, or
  • an invalid pointer value.

指针类型的值,该值是指向或超过结束符的指针 对象代表内存中第一个字节的地址 ([intro.memory])由对象或内存中的第一个字节占用 结束存储后分别由该对象占用. [ 注意:指向对象([expr.add])末尾的指针不是 被认为指向对象类型不相关的对象 可能位于该地址.指针值在以下情况下变为无效 它表示的存储已达到其存储期限的末尾;看 [basic.stc]. —尾注]出于指针算术目的 ([expr.add])和比较([expr.rel],[expr.eq]),即过去的指针 n个元素的数组x的最后一个元素的末尾被认为 等效于x的假设数组元素n的指针 并且类型T的对象(不是数组元素)被认为是 属于一个类型为T的元素的数组.

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see [basic.stc]. — end note ] For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), a pointer past the end of the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical array element n of x and an object of type T that is not an array element is considered to belong to an array with one element of type T.

p = reinterpret_cast<int*>(42);不适合可能的值列表.并且:

p = reinterpret_cast<int*>(42); does not fit into the list of possible values. And:

C ++ 17§8.2.10/5 [expr.reinterpret.cast]

整数类型或枚举类型的值可以显式地表示 转换为指针.指针转换为的整数 足够的大小(如果实现中存在此类大小)并返回 相同的指针类型将具有其原始值;之间的映射 指针和整数是实现定义的. [ 笔记: 除第6.7.4.3条所述外,此类转换的结果将为 不能是安全得出的指针值. —尾注]

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [ Note: Except as described in 6.7.4.3, the result of such a conversion will not be a safely-derived pointer value. — end note ]

C ++标准似乎没有更多地说明整数到指针的转换.查找C17标准:

C++ standard does not seem to say more about the integer to pointer conversion. Looking up the C17 standard:

C17§6.3.2.3/5 (强调我的意思)

C17 §6.3.2.3/5 (emphasis mine)

整数可以转换为任何指针类型.除了作为 先前指定的结果是实现定义的,可能不是 正确对齐,可能未指向所引用的实体 类型,并且可能是陷阱表示 .68)

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.68)

C17§6.2.6.1/5

某些对象表示形式不必表示 对象类型.如果对象的存储值具有这样的 表示形式,并由不具有的左值表达式读取 字符类型,行为未定义.如果这样的表示是 由修改对象的全部或任何部分的副作用产生的 通过没有字符类型的左值表达式, 行为是不确定的50)这种表示称为陷阱 表示形式.

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.50) Such a representation is called a trap representation.

对我来说,似乎[basic.compound]中不适合列表的任何值都是陷阱表示,因此p = reinterpret_cast<int*>(42);是UB.我对么?还有其他使p = reinterpret_cast<int*>(42);不确定的东西吗?

To me, it seems like any value that does not fit into the list in [basic.compound] is a trap representation, thus p = reinterpret_cast<int*>(42); is UB. Am I correct? Is there something else making p = reinterpret_cast<int*>(42); undefined?

推荐答案

这不是UB,而是实现定义的,您已经引用了原因(第8.2.10/5节[expr.reinterpret.cast]).如果指针具有无效的指针值,则不一定意味着它具有陷阱表示形式.它可以具有陷阱表示,并且编译器必须对此进行记录.您所拥有的只是一个不安全来源的指针.

This is not UB, but implementation-defined, and you already cited why (§8.2.10/5 [expr.reinterpret.cast]). If a pointer has invalid pointer value, it doesn't necessarily mean that it has a trap representation. It can have a trap representation, and the compiler must document this. All you have here is a not safely-derived pointer.

请注意,我们始终会生成具有无效指针值的指针:如果delete释放了一个对象,则指向该对象的所有指针都具有无效的指针值.

Note, that we generate pointers with invalid pointer value all the time: if an object is freed by delete, all the pointers which pointed to this object have invalid pointer value.

使用结果指针也是定义的实现(不是UB) :

Using the resulting pointer is implementation defined as well (not UB):

[...]如果glvalue引用的对象包含无效的指针值([basic.stc.dynamic.deallocation],[basic.stc.dynamic.safety]),则行为是实现定义的.

[...] if the object to which the glvalue refers contains an invalid pointer value ([basic.stc.dynamic.deallocation], [basic.stc.dynamic.safety]), the behavior is implementation-defined.

这篇关于将整数转换为指针总是定义良好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆