2

The following sometimes fails after compiling for x86 with Visual Studio 16.8.1:

#include <cassert>
#include <cstdint>

struct X { uint64_t value; };

int main() {
    X x;
    assert(reinterpret_cast<uintptr_t>(&x) % alignof(X) == 0);
}

Interestingly, the assert doesn't trigger if X has an explicit alignment specifier: struct alignas(uint64_t) X.

Am I correct to assume this is a compiler bug and not some quirk of the C++ standard?

Valentin Milea
  • 3,186
  • 3
  • 28
  • 29

1 Answers1

1

It's a bug.

On x86, some operations may incur a performance penalty unless the operand is naturally aligned. Apparently Visual C++ has a nonconformant alignof operator which returns the natural alignment instead of the required alignment for a type. When building with MSVC for 32-bit, the natural alignment of uint64_t / double is 8, while its required alignment is 4. So in the code above the address of x must be a multiple of 4, but not necessarily a multiple of alignof(X).

This baffling behavior is underlined by uint64_t x; not having the same meaning as alignas(uint64_t) uint64_t x;. Only the latter has the expected alignment.

See also: GCC fixing a similar bug and associated libc++ updates.

Valentin Milea
  • 3,186
  • 3
  • 28
  • 29
  • Reported [here](https://developercommunity.visualstudio.com/content/problem/1258506/visual-c-alignof-is-not-conformant-on-x86.html). – Valentin Milea Nov 17 '20 at 15:32
  • Documented [here](https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-160#conflicts-with-the-x86-compiler). – Hans Passant Nov 19 '20 at 12:40
  • Thanks for the link. This explains the alignment of stack variables on x86. But it doesn't address `alignof`, which should report the _required_ alignment of 4. – Valentin Milea Feb 01 '21 at 08:03