从转换整数值获得的指针执行间接访问肯定是 UB 吗?

Is performing indirection from a pointer acquired from converting an integer value definitely UB?

考虑这个例子

int main(){
  std::intptr_­t value = /* a special integer value */; 
  int* ptr = reinterpret_­cast<int*>(value ); // #1
  int v = *ptr;  // #2
}

[expr.reinterpret.cast] p5 说

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.

至少,步骤 #1 是实现定义的。对于step#2,在我看来,我觉得有四种可能,分别是

  1. The implementation does not support such a conversion, and implementation does anything for it.
  2. The pointer value is exactly the address of an object of type int, the result is well-formed.
  3. The pointer value is the address of an object other than the int type, the result is UB.
  4. The pointer value is an invalid pointer value, the indirection is UB.

这意味着通过指针 ptr 的间接行为将取决于实现。如果实现采用选项2,那肯定不是UB。所以,我想知道这个案例是不是肯定是UB还是肯定是UB?如果是后者,哪些条款强烈说明了这种行为?

Is performing indirection from a pointer acquired from converting an integer value definitely UB?

不总是。这是一个绝对不是 UB 的例子:

int i = 42;
std::intptr_t value = reinterpret_cast<std::intptr_t>(&i); 
int* ptr = reinterpret_cast<int*>(value);
int v = *ptr;

这是因为将指针转换为足够大小的整数并返回相同的指针类型可以保证产生与您引用的规则中所述相同的指针值。由于原始指针值对间接有效,因此转换后的值也是如此。

除了你引用的内容之外,该标准没有什么可说的。如果该整数值是从指针到整数的转换中获取的,则该标准仅保证整数到指针转换的含义。所有其他整数到指针转换的含义都是实现定义的。

这意味着 关于它们的一切 都是“实现定义的”:它们产生什么结果以及使用这些结果会做什么。毕竟,指针到整数到指针的往返说明您得到了“原始值”。结果指针具有“原始值”这一事实意味着它的行为与您复制原始指针本身完全一样。所以标准就不用多说了。

从实现定义的整数到指针转换中获取的指针的行为是...实现定义的。如果一个实现说支持这样的转换,它必须说明支持的转换的结果是什么。也就是说,如果实现支持转换为 int* 的某些“特殊整数值”,则它必须说明该转换的结果是什么。这包括诸如它是否指向实际的 int 或其他任何东西。