alignas in structs on 32-bit platforms
Asked Answered
T

1

8

I am getting unexpected results when running the following code for 32-bit x86 linux (compiler flags: g++ -std=c++14 -m32). I tried gcc and clang.

#include <iostream>
using namespace std;

struct S1
{
  uint64_t a;
  uint32_t b;
};

struct S2
{
  alignas(uint64_t) char a[8];
  uint32_t b;
};

int main()
{
  cout << "sizeof(S1)=" << sizeof(S1) << endl;
  cout << "sizeof(S2)=" << sizeof(S2) << endl;
}

The output is:

sizeof(S1)=12
sizeof(S2)=16

What is happening here? Why are S1 and S2 of different size? As I understand it, 64 bit integer values are aligned to 32 bit on 32-bit x86 machines. This does explain why the size of S1 is 12 bytes. But why does this not apply to S2?

Typal answered 6/1, 2016 at 13:27 Comment(5)
Possibly cache row alignment for character array a includes one extra 4-byte block for the array for make S2 16 bytes? Possibly related: #17091882Undefined
This is not an answer but progress. alignas(uint64_t) is defined as the same as alignas(alignof(uint64_t)). If you add cout << alignof(uint64_t) << endl ; to the example you'll get an output of 8 (gcc at least). So the question should be 'why does gcc think alignof(uint64_t) is 8 when it's 4 on the platform in question. NB: It has to be 4 because sizeof(S1) is 12.Toggery
To see if the difference in size may be related to the fact that you are using a char[8], Could you please replace, in S2: alignas(uint64_t) char a[8]; with another 64 bits type, like for example a double?Smashandgrab
@Smashandgrab I think that will only confuse matters. alignof(double) is typically 8 anyway. So sizeof(S2) would be 16 without the alignas(uint64_t). As I mentioned gcc says alignof(uint64_t) is 8. That appears to be the root of the problem.Toggery
This seems to be related to this question. And possibly to this thread of gcc mailing listSmashandgrab
B
4

The alignof keyword measures the alignment of a type as a complete object; i.e. when it is allocated as an individual object or array element. This is not necessarily the same as the alignment requirements of that type as a subobject; Are members of a POD-struct or standard layout type guaranteed to be aligned according to their alignment requirements?

The alignment of a 64-bit integer within a struct is mandated by the x386 ABI at 4 bytes; gcc is not at liberty to change this, as it would break binary compatibility with other object files and programs. However, it can align complete-object 64-bit integers to 8 bytes, as doing so does not affect the ABI, and makes for more efficient access to memory.

Blancablanch answered 6/1, 2016 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.