6

According to MSDN, the /Zp command defaults to 8, which means 64-bit alignment boundaries are used. I have always assumed that for 32-bit applications, the MSVC compiler will use 32-bit boundaries. For example:

struct Test
{
   char foo;
   int bar;
};

The compiler will pad it like so:

struct Test
{
   char foo;
   char padding[3];
   int bar;
};

So, since /Zp8 is used by default, does that mean my padding becomes 7+4 bytes using the same example above:

struct Test
{
   char foo;
   char padding1[7];
   int bar;
   char padding2[4];
}; // Structure has 16 bytes, ending on an 8-byte boundary

This is a bit ridiculous isn't it? Am I misunderstanding? Why is such a large padding used, it seems like a waste of space. Most types on a 32-bit system aren't even going to use 64-bits, so the majority of variables would have padding (probably over 80%).

void.pointer
  • 24,859
  • 31
  • 132
  • 243
  • Can you clarify on the `7+4`? I'm somewhat confused by the question right now. – Mysticial Dec 07 '11 at 04:42
  • @Mysticial: I updated my OP with another example to show you what I mean by that. Sorry for the confusion. – void.pointer Dec 07 '11 at 04:49
  • Thanks for the clarification. I just tested your first struct and the size is only 8 bytes, padded via second struct snippet. So I'm not able to repro what you're getting. (or at least what you think you should be getting) – Mysticial Dec 07 '11 at 04:52

2 Answers2

11

That's not how it works. Members are aligned to a multiple of their size. Char to 1 byte, short to 2, int to 4, double to 8. The structure is padded at the end to ensure the members still align correctly when the struct is used in an array.

A packing of 8 means it stops trying to align members that are larger than 8. Which is a practical limit, the memory allocator doesn't return addresses aligned better than 8. And double is brutally expensive if it isn't aligned properly and ends up straddling a cache line. But otherwise a headache if you write SIMD code, it requires 16 byte alignment.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • So then since the default alignment is 8 according to MSDN, then the last code snippet in my OP is what the alignment padding looks like? If not, please explain. – void.pointer Dec 07 '11 at 15:20
  • 1
    @Robert: Your last code is wrong. It will be padded like this `char foo; pad[3] ; int bar;` Because `int` is the biggest member in the structure. You should read very carefully what Hans said – Benjamin Dec 16 '11 at 17:36
3

That does not mean every member is aligned on an 8byte boundary. Read a little more carefully:

the smaller member type or n-byte boundaries

The key here is the first part- "smaller member type". That means that members with less alignment might be aligned less, effectively.

struct x {
    char c;
    int y;
};
std::cout << sizeof(x);
std::cout << "offsetof(x, c) = " << offsetof(x, c) << '\n';
std::cout << "offsetof(x, c) = " << offsetof(x, y) << '\n';

This yields 8, 0, 4- meaning that in fact, the int is only padded to a 4byte alignment.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    The last part of your answer is incorrect. Remove the int from the structure and note that sizeof() doesn't return 8. – Hans Passant Dec 07 '11 at 05:05