c++ - Is converting an integer to a pointer always well defined?
问题描述
Is this valid C++?
int main() {
int *p;
p = reinterpret_cast<int*>(42);
}
Assuming I never dereference p
.
Looking up the C++ standard, we have
C++17 §6.9.2/3 [basic.compound]
3 Every value of pointer type is one of the following:
- 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.
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);
does not fit into the list of possible values. And:
C++17 §8.2.10/5 [expr.reinterpret.cast]
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++ standard does not seem to say more about the integer to pointer conversion. Looking up the C17 standard:
C17 §6.3.2.3/5 (emphasis mine)
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)
and
C17 §6.2.6.1/5
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.
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])。如果一个指针具有无效的指针值,并不一定意味着它具有陷阱表示。它可以有一个陷阱表示,编译器必须记录这一点。您在这里所拥有的只是一个不安全派生的指针。
请注意,我们总是生成具有无效指针值的指针:如果一个对象被释放delete
,则指向该对象的所有指针都具有无效的指针值。
使用结果指针也是定义的实现(不是UB):
[...] 如果泛泛值引用的对象包含无效的指针值([basic.stc.dynamic.deallocation]、[basic.stc.dynamic.safety]),则行为是实现定义的。
推荐阅读
- sql - 如何在 phpmyadmin 中导入这个 github repo 的 sql 文件
- java - Onhandleintent 昨天工作,现在没有
- content-management-system - Magento 2.3.3:如何在 CMS 页面中获取 form_key
- r - 删除包含零的单元格但保留该行
- apache-spark - 如何以逗号分隔的形式显示火花流作业的数据帧输出?
- javascript - 如何在 TypeScript 中将 PFX 证书转换为 PEM 证书(通过使用 openssl 或任何其他包)?
- python - Python - Spotify API 返回错误 400“格式错误的 JSON”
- pandas - 将平均行添加到包含“-”的数据帧
- android - 仅在 Android 中禁用屏幕录制
- android - Google Awareness Snapshot API 已弃用的替代方案