这是否违反了严格的别名或指针对齐规则?

时间:2016-06-08 23:24:28

标签: c++ pointers

我在char缓冲区中交换字节:

char* data; // some char buffer
uint16_t* data16 = reinterpret_cast<uint16_t*>(data);

// For debugging:
int align = reinterpret_cast<uintptr_t>(data) % alignof(uint16_t);
std::cout << "aligned? " << align << "\n";

for (size_t i = 0; i < length_of_data16; i++) {
#if defined(__GNUC__) || defined(__clang__)
  data16[i] = __builtin_bswap16(data16[i]);
#elif defined(_MSC_VER)
  data16[i] = _byteswap_ushort(data16[i]);
#endif
}

我从char*投射到uint16_t*,这会引发一面旗帜,因为它会投射到更严格对齐的类型。

但是,代码运行正常(在x86上),即使调试代码打印1(如同,未对齐)。在程序集中我看到MOVDQU,我认为这意味着编译器认识到这可能没有对齐。

这与this question类似,答案是&#34;这不安全。&#34;以上代码是仅适用于某些体系结构和某些编译器,还是这两个问题之间存在细微差别,使上述代码有效?

(不太重要:与我在线阅读的内容一致,此代码的对齐和未对齐执行之间也没有明显的性能差异。)

1 个答案:

答案 0 :(得分:1)

如果alignof(unit16_t) != 1,则此行可能会因对齐而导致未定义的行为:

uint16_t* data16 = reinterpret_cast<uint16_t*>(data);

在之后进行对齐检查并不好;对于编译器,可以将检查硬编码为1,因为它知道正确的代码无法达到该点。

在标准C ++中,为了使此检查有意义,它必须在强制转换之前发生,然后如果检查失败则不能执行强制转换。 (UB可以时间旅行)。

当然,个别编制者可能会选择定义未由标准定义的行为,例如也许g ++定位x86或x64包含一个定义,允许你形成未对齐的指针并取消引用它们。

没有严格的别名冲突,因为标准不涵盖__builtin_bswap16,我们假设g ++以与自身一致的方式实现它。无论如何,MSVC都不会进行严格的别名优化。