使用Visual Studio 16.8.1为x86编译后,以下内容有时会失败:
#include <cassert>
#include <cstdint>
struct X { uint64_t value; };
int main() {
X x;
assert(reinterpret_cast<uintptr_t>(&x) % alignof(X) == 0);
}
有趣的是,如果X
有一个显式对齐说明符:struct alignas(uint64_t) X
,则断言不会触发。
我认为这是一个编译器错误,而不是C++标准的一些怪癖,这是正确的吗?
这是一个错误。
在x86上,除非操作数自然对齐,否则某些操作可能会导致性能损失。显然,Visual C++有一个不一致的alignof
运算符,它返回自然对齐,而不是类型所需的对齐。当使用32位的MSVC构建时,uint64_t
/double
的自然对齐为8,而其所需对齐为4。因此,在上面的代码中,x
的地址必须是4的倍数,但不一定是alignof(X)
的倍数。
uint64_t x;
与alignas(uint64_t) uint64_t x;
的含义不同,这一令人困惑的行为得到了强调。只有后者具有预期的一致性。
另请参阅:GCC修复了一个类似的错误和相关的libc++更新。