0

I was looking at a small program -

#include<iostream>

class A
{
    bool a; 
    bool c;     
};

int main()
{
    std::cout << sizeof(A) << std::endl;
    return 0;
}

Here, it shows the size of class A as 2 bytes. But, if I add another integer data member to this class as -

class A
    {
        int b;
        bool a; 
        bool c;     
    };

Now, it shows the size of class A as 8 bytes instead of 6 bytes. Why compiler does padding in second case & why not in first case?

hroptatyr
  • 4,702
  • 1
  • 35
  • 38
yuvi
  • 1,032
  • 1
  • 12
  • 22

3 Answers3

3

The size of a structure is a multiple of the alignment requirement of a data member with the largest alignment requirement. This is so that when an array of structures is used there is no padding between the elements of the array and the alignment requirements for each data member of the structure is satisfied.

In the first case, the largest alignment requirement is alignof(bool) which is 1, so the size of the structure is a multiple of 1.

In the second case, the largest alignment requirement is alignof(int) which is 4, so the size of the structure is a multiple of 4.

Try adding a double member with the alignment requirement of 8.

A rule of thumb to minimize padding in structures is to arrange data members from the largest alignment requirement to the smallest, e.g. doubles followed by pointers followed by longs followed by ints followed by shorts followed by bools followed by chars.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 1
    A double typically only needs a 4 byte alignment. Alignment requirements and size are different things. – nwp Jun 16 '14 at 10:57
  • Thanks..I was about to ask this and than I saw your comment..:) – yuvi Jun 16 '14 at 11:00
  • @nwp You are wrong on both of your points. Try `std::cout << alignof(double) << '\n';` in g++ on Linux. – Maxim Egorushkin Jun 16 '14 at 11:00
  • I believe that is a bug. If you put a `double` in a `struct S` then `alignof(S)` will give you a 4. Or you are on weird hardware. Did anyone ever ask why `alignof(double) == 8` and `alignof(struct{double})==4`? – nwp Jun 16 '14 at 11:04
  • Actually, `g++` and `clang++` give me 8 bytes as `alignof(double)`, both with 64 and 32 bits targets. – Massa Jun 16 '14 at 11:07
  • @Massa What happens when you put the `double` in a struct? There is probably a reason for that, I just don't know it. – nwp Jun 16 '14 at 11:08
  • @nwp On x86-64 the alignment of the structure with a sole double member is 8. For i686 it is 4. See `-malign-double` gcc flag. – Maxim Egorushkin Jun 16 '14 at 11:11
  • @nwp then I (yes, I concur, strangely) get 4 in 32-bits and 8 in 64-bits. If I had to guess, I would say that proably in x86 32-bits machines, the protocol to get to parts of an struct (indirect loads via edx+offset or something?) needs/wants less alignment than to get to "free" variables (usually stored in registers and loaded directly from the memory to a register) – Massa Jun 16 '14 at 11:11
  • @MaximYegorushkin nice pointers! http://stackoverflow.com/questions/2457182/c-malign-double-compiler-flag – Massa Jun 16 '14 at 11:12
  • I also found something: [why is a double member in struct not aligned on 8 byte boundary?](http://stackoverflow.com/questions/14893802/why-is-a-double-member-in-struct-not-aligned-on-8-byte-boundary) Apparently aligning a double on 8 bytes is slightly faster so it is done for doubles, but for structs the speedup is not worth the loss in space. – nwp Jun 16 '14 at 11:13
  • @nwp there's our reason: compatibility with idiotic mircosoft compilers... http://www.delorie.com/gnu/docs/gcc/gcc_10.html – Massa Jun 16 '14 at 11:13
2

Imagine you have an Array of As. The second A in the array would have its member b misaligned if there was no additional padding. That said the compiler can choose whatever it feels like. Misaligned accesses cost runtime, padding costs space. Your compiler favored runtime.

nwp
  • 9,623
  • 5
  • 38
  • 68
1

The only things the compiler must do is align the first member so that the address of that member is the same as the address of the structure and preserve the order of the members as specified by the class.

Other than these, the compiler is free to do what it wants (unless you tell it otherwise using packing directives which vary from compiler to compiler). It will probably pack members in order to optimise runtime speed.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483