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?

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: stackoverflow.com/questions/17091382/… Commented Jan 6, 2016 at 13:39
  • 2
    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. Commented Jan 6, 2016 at 13:51
  • 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? Commented Jan 6, 2016 at 14:09
  • @arainone 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. Commented Jan 6, 2016 at 14:17
  • 2
    This seems to be related to this question. And possibly to this thread of gcc mailing list Commented Jan 6, 2016 at 14:38

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.