在C++ 14中,未指定的指针转换如何表现?

M.M*_*M.M 6 c++ pointers language-lawyer reinterpret-cast c++14

某些指针强制转换的结果被描述为未指定.例如,[expr.static.cast]/13:

类型为"指向cv1 void的指针"的prvalue可以转换为类型为"指向cv2 T的指针"的prvalue [...]如果原始指针值表示内存中字节的地址A并且A满足对齐要求然后,结果指针值表示与原始指针值相同的地址,即A. 未指定任何其他此类指针转换的结果.

我的问题是:在比对的情况下没有满足,有哪些可能的结果?

例如,是否允许以下​​结果?

  • 空指针
  • 无效的指针值(即指向不分配存储大小的指针T)
  • 指向T内存完全独立部分的有效指针

代码示例供参考:

#include <iostream>

int main(int argc, char **argv)
{
    int *b = (int *)"Hello, world";   // (1)

    *b = -1;                           // (2)
    std::cout << argc << '\n';
}
Run Code Online (Sandbox Code Playgroud)

线(1)触发从[expr.static.cast]/13我的上面的引用,因为它是一个reinterpret_cast其由[expr.reinterpret.cast]/7,其限定在以下方面的转化覆盖static_cast荷兰国际集团通过void *.

如果未指定的结果可能是无效的指针值,则行(1)可能会导致硬件陷阱.(参考:N4430,它澄清了C++ 14和C++ 11中的类似措辞).

推论问题:是否有任何情况下哪一行1会导致未定义的行为?(我不认为在这个阶段;因为C++ 14无效指针值读取是实现定义的或导致硬件陷阱).


同样有趣的是,(2)在大多数情况下,由于严格的别名违规(也可能是其他原因),行将是未定义的行为,但是如果未指定的结果可能&argc则此程序可以输出-1而不会触发未定义的行为!

Sha*_*our 3

我的问题是:在不满足对齐的情况下,可能的结果是什么?

据我所知,N4303:指针安全和放置新部分回答了这个问题,尽管有些间接。本文引用了CWG 问题 1412:指定指针转换中的问题,这导致了您引用的[expr.static.cast]/13的更改,具体添加了:

[...]如果原始指针值代表内存中某个字节的地址A,并且A满足T的对齐要求,则结果指针值代表与原始指针值相同的地址,即A。结果任何其他此类指针转换均未指定。[...]

关于这一变化N4303说(强调我的):

在通过 DR 1412 [CWG1412] 决议之前,bp 的值在其初始化以及随后通过 new 表达式传递给运算符 new 时未指定。所述指针可能为空、未充分对齐或有其他使用危险。

因此,未指定的转换可能会导致:

  • 空指针
  • 指针未充分对齐
  • 使用危险的指针