Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.
For compatibility with Microsoft
Windows compilers, GCC supports a set
of #pragma directives which change the
maximum alignment of members of
structures (other than zero-width
bitfields), unions, and classes
subsequently defined. The n value
below always is required to be a small
power of two and specifies the new
alignment in bytes.
#pragma pack(n) simply sets the new alignment.
#pragma pack() sets the alignment to the one that was in
effect when compilation started (see
also command line option
-fpack-struct[=] see Code Gen Options).
#pragma pack(push[,n]) pushes the current alignment setting on an
internal stack and then optionally
sets the new alignment.
#pragma pack(pop) restores the alignment setting to the one saved at
the top of the internal stack (and
removes that stack entry). Note that
#pragma pack([n]) does not influence this internal stack; thus it is
possible to have #pragma pack(push)
followed by multiple #pragma pack(n)
instances and finalized by a single
#pragma pack(pop).
Some targets, e.g. i386 and powerpc,
support the ms_struct #pragma which
lays out a structure as the documented
__attribute__ ((ms_struct)).
#pragma ms_struct on turns on the layout for structures declared.
#pragma ms_struct off turns off the layout for structures declared.
#pragma ms_struct reset goes back to the default layout.
In C, the compiler is allowed to dictate some alignment for every primitive type. Typically the alignment is the size of the type. But it's entirely implementation-specific.
Padding bytes are introduced so every object is properly aligned. Reordering is not allowed.
Possibly every remotely modern compiler implements #pragma pack which allows control over padding and leaves it to the programmer to comply with the ABI. (It is strictly nonstandard, though.)
From C99 §6.7.2.1:
12 Each non-bit-field member of a
structure or union object is aligned
in an implementation- defined manner
appropriate to its type.
13 Within a
structure object, the non-bit-field
members and the units in which
bit-fields reside have addresses that
increase in the order in which they
are declared. A pointer to a structure
object, suitably converted, points to
its initial member (or if that member
is a bit-field, then to the unit in
which it resides), and vice versa.
There may be unnamed padding within a
structure object, but not at its
beginning.
It's implementation-specific, but in practice the rule (in the absence of #pragma pack or the like) is:
Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.)
If necessary, padding is added between struct members, to ensure that the latter one uses the correct alignment.
Each primitive type T requires an alignment of sizeof(T) bytes.
So, given the following struct:
struct ST
{
char ch1;
short s;
char ch2;
long long ll;
int i;
};
ch1 is at offset 0
a padding byte is inserted to align...
s at offset 2
ch2 is at offset 4, immediately after s
3 padding bytes are inserted to align...
ll at offset 8
i is at offset 16, right after ll
4 padding bytes are added at the end so that the overall struct is a multiple of 8 bytes. I checked this on a 64-bit system: 32-bit systems may allow structs to have 4-byte alignment.
So sizeof(ST) is 24.
It can be reduced to 16 bytes by rearranging the members to avoid padding:
struct ST
{
long long ll; // @ 0
int i; // @ 8
short s; // @ 12
char ch1; // @ 14
char ch2; // @ 15
} ST;