0

I was exploring memory alignment and padding, and thought that I got the hang of it until I came across this:

struct Example {
   int x1; // 4
   char c; // 1 + 3 padding
   int x2; // 4
};

static_assert(sizeof Example == 12, "Incorrect size");  // OK

struct Example2 {
   long long x; // 8
   Example y;   // 12
                // 4 bytes padding
};

static_assert(sizeof Example2 == 24, "Incorrect size"); // OK
    
struct Example3 {
   unsigned char x[8];     // 8
   unsigned char y[12];    // 12
                           // 4 bytes padding??
};

static_assert(sizeof Example3 == 24, "Incorrect size"); // ERROR

I am on a 64-bit system, using MSVC x64 compiler. Why does it always calculate memory alignments for structs with only array types as 1?

Zaki
  • 107
  • 9
  • 2
    You might find this answer helpful: https://stackoverflow.com/a/38144117/16483288 – fjs Jun 22 '23 at 02:24
  • The example is clearly for a 32 bit system. And it shows you that you should always know what architecture you are on and what compiler settings are used. And for portable code you should never assume anything about memory layout. – Pepijn Kramer Jun 22 '23 at 03:16
  • Sometimes [in C++ arrays are converted to pointer types](https://stackoverflow.com/a/3959761/22081063), but I'm not exactly certain that is what is happening here. – Chipster Jun 22 '23 at 03:29
  • Also, not sure if this is relevant, but 8 + 12 = 20, not 24. My compiler is just fine if you change 24 to 20 in that third assertion. – Chipster Jun 22 '23 at 03:35
  • @PepijnKramer The padding is not determined by the word size, but by the alignment of each data type. So, your assumption that I am on a x32 arch bc memory alignment in the above examples is 4, is not correct. – Zaki Jun 22 '23 at 13:16
  • @Chipster I don't think that's the case, if arrays are converted to pointer types in this example, then the memory alignment would be 8 bytes, which means sizeof Example3 == 16 but it isn't. – Zaki Jun 22 '23 at 13:22
  • 1 byte char + 3 bytes padding looks like 4 bytes alignment to me – Pepijn Kramer Jun 22 '23 at 14:04
  • @PepijnKramer It is 4 bytes alignment bc the memory alignment requirement of a struct is determined by the data type with the strictest alignment within that struct, in that case it was `int`, which has an alignment of 4 bytes. However, from my understanding so far, you can't rely on any hard-and-fast rules. It's a function of the compiler you use and the compilation options you choose as you mentioned before and I have used default settings. – Zaki Jun 22 '23 at 15:27
  • I see and Yup AFAIK alignment is implementation defined. I never write code making assumptions on exact memory layout. – Pepijn Kramer Jun 22 '23 at 15:31

1 Answers1

1

long long x; requires the alignment 8, the compiler adds the 4 bytes padding to make elements in an array of Example2 properly aligned.

unsigned char x[8]; doesn't require any alignment, the elements in an array of Example3 do not need to be aligned, thus the compiler doesn't add padding bytes, but it can add them, it's implementation specific.

273K
  • 29,503
  • 10
  • 41
  • 64
  • Doesn't an array strictly require that their elements to be contiguously allocated? Which means an array of 8 chars needs an alignment of 8 bytes to achieve that condition? right? – Zaki Jun 22 '23 at 02:16
  • 2
    @Zaki Why do you think that _"an array of 8 chars needs an alignment of 8 bytes"_? A `char` (or `unsigned char`, or `signed char`) requires only one byte in memory, so it can be stored at any address (without the need of alignment). An array of 8 `char`s (or `unsigned char`s, or `signed char`s) is just a sequence of 8 one-byte elements, stored contiguously. Two consecutive arrays of `char`s (or `unsigned char`s, or `signed char`s), of any length, can also be stored contiguously, without the risk that any of the elements will end up unaligned (because the elements are one-byte only anyway). – heap underrun Jun 22 '23 at 03:56
  • Thank you for the clarification. This answer helped me to understand the missing pieces that I had with memory alignment too: https://stackoverflow.com/a/55920216/12137626 – Zaki Jun 22 '23 at 13:29