Data alignment is a complex matter, as illustrated by the following example (that you can even draw to make your own experiments):
#include <stdio.h>
struct A { /* no padding */
char a[3];
};
struct B {
int a;
char b[3];
/* one byte of padding (in 32bit arch) added here */
};
struct C { /* no padding again */
char a[4];
char b[3];
};
struct D {
char a[3];
/* one byte of padding to ensure alignment of next field */
int b;
char c[3];
/* one byte of padding to ensure alignment of whole struct in arrays */
}
#define P(X) printf("sizeof struct %s == %ld\n", #X, sizeof (struct X))
int main()
{
P(A);
P(B);
P(C);
P(D);
} /* main */
As you see, the required alignment (1 byte) of the struct A
type is allowing to place it anywhere in memory and determines that no padding bytes are necessary to determine the sizeof
value.
In the second example, we introduced an int
value, which forces the whole struct
to be word aligned (so an int is accessible in a properly aligned memory address) so this time, the compiler has padded (at the end of the structure) for extra bytes, so any array type of the specified type gets correctly aligned, and its int
field is accessed at a valid address.
In the third example, I illustrate that the effect of the padding in the second example is due to the int
field present in the struct, as the third example has a same size field, but this time a non requiring alignment field, so no padding has been inserted, as all the individual data types inside need alignment of 1.
The output (on my system, a MAC OSX system) is:
sizeof struct A == 3
sizeof struct B == 8
sizeof struct C == 7
sizeof struct D == 12