何时类型惩罚指针在实践中是安全的?

Ser*_*nov 5 c++ strict-aliasing undefined-behavior

我的一位同事正在研究与二进制数据阵列一起使用的C++代码.在某些地方,他的代码就像

char *bytes = ...
T *p = (T*) bytes;
T v = p[i]; // UB
Run Code Online (Sandbox Code Playgroud)

在这里,T有时可以shortint(分别假设16位和32位).

现在,与我的同事不同,我属于"没有UB,如果可能的话"阵营,而他更像是"如果它有效,那就没关系".我正在努力试图说服他.

鉴于:

  1. bytes 真的来自这个编译单元之外的某个地方,从一些二进制文件中读取.

  2. 可以安全地假设数组实际上包含本机字节序中的整数.

在实践中,鉴于MSVC 2017和gcc 4.8等主流C++编译器以及Intel x64硬件,这样的事情真的很安全吗?我知道它不会T是,比如说,float(过去曾被它咬过).

Jar*_*d42 5

char* 可以在不破坏严格别名规则的情况下为其他实体设

只有在最初p + i不是T原始代码时,您的代码才是UB .

char* byte = (char*) floats;
int *p = (int*) bytes;
int v = p[i]; // UB
Run Code Online (Sandbox Code Playgroud)

char* byte = (char*) floats;
float *p = (float*) bytes;
float v = p[i]; // OK
Run Code Online (Sandbox Code Playgroud)

如果原点byte是"未知",则编译器不能从UB中获益以进行优化,并且应该假设我们处于有效的情况并根据生成代码.但你如何保证它是未知的?即使在TU之外,像Link-Time Optimization这样的东西也许可以提供隐藏的信息.