这是否违反了严格的锯齿或指针对齐规则



我正在交换字符缓冲区中的字节:

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(如 in,未对齐)。在程序集中,我看到了MOVDQU,我认为这意味着编译器认识到这可能未对齐。

看起来类似于这个问题,答案是"这不安全"。上面的代码是否仅适用于某些体系结构和某些编译器,或者这两个问题之间存在细微差异,使上述代码有效?

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

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

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

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

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

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

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

最新更新