Sets the alignment of all aggregate members to a specified byte boundary.
If the byte boundary number is smaller than the natural alignment of a member, padding bytes are removed, thereby reducing the overall structure or union size.
The syntax and semantics of this pragma are different depending on the setting of the -qpack_semantic option.
Default #pragma pack syntax (-qpack_semantic=ibm in effect) >>-#--pragma--pack--(--+--------+--)--------------------------->< +-nopack-+ +-number-+ '-pop----'
#pragma pack syntax with -qpack_semantic=gnu in effect >>-#--pragma--pack--(--+-----------------------------+--)------>< +-number--push--+-----------+-+ | '-,--number-' | '-pop-------------------------'
Members of aggregates (structures, unions, and classes) are aligned on their natural boundaries and a structure ends on its natural boundary. The alignment of an aggregate is that of its strictest member (the member with the largest alignment requirement).
The #pragma pack directive applies to the definition of an aggregate type, rather than to the declaration of an instance of that type; it therefore automatically applies to all variables declared of the specified type.
The #pragma pack directive modifies the current alignment rule for only the members of structures whose declarations follow the directive. It does not affect the alignment of the structure directly, but by affecting the alignment of the members of the structure, it may affect the alignment of the overall structure.
The #pragma pack directive cannot increase the alignment of a member, but rather can decrease the alignment. For example, for a member with data type of short, a #pragma pack(1) directive would cause that member to be packed in the structure on a 1-byte boundary, while a #pragma pack(4) directive would have no effect.
#pragma pack(2)
struct A{
int a:31;
int b:2;
}x;
int main(){
printf("size of S = %d\n", sizeof(s));
}
When compiled and run, the output is:
size of S = 6
But if you remove the #pragma pack directive, you get this output:
size of S = 8
#pragma pack(1)
struct S;
#pragma pack(4)
struct S { int i, j, k; };
#pragma pack (4) // 4-byte alignment
struct nested {
int x;
char y;
int z;
};
#pragma pack(1) // 1-byte alignment
struct packedcxx{ char a;
short b;
struct nested s1; // 4-byte alignment
};
If more than one #pragma pack directive appears in a structure defined in an inlined function, the #pragma pack directive in effect at the beginning of the structure takes precedence.
// header file file.h
#pragma pack(1)
struct jeff{ // this structure is packed
short bill; // along 1-byte boundaries
int *chris;
};
#pragma pack(pop) // reset to previous alignment rule
// source file anyfile.c
#include "file.h"
struct jeff j; // uses the alignment specified
// by the pragma pack directive
// in the header file and is
// packed along 1-byte boundaries
struct s_t {
char a;
int b;
short c;
int d;
}S;
| Default mapping: | With #pragma pack(1): |
|---|---|
| size of s_t = 16 | size of s_t = 11 |
| offset of a = 0 | offset of a = 0 |
| offset of b = 4 | offset of b = 1 |
| offset of c = 8 | offset of c = 5 |
| offset of d = 12 | offset of d = 7 |
| alignment of a = 1 | alignment of a = 1 |
| alignment of b = 4 | alignment of b = 1 |
| alignment of c = 2 | alignment of c = 1 |
| alignment of d = 4 | alignment of d = 1 |
union uu {
short a;
struct {
char x;
char y;
char z;
} b;
};
union uu nonpacked[2];
Since the largest alignment
requirement among the union members is that of short a,
namely, 2 bytes, one byte of padding is added at the end of each union
in the array to enforce this requirement: ┌───── nonpacked[0] ─────────── nonpacked[1] ───┐
│ │ │
│ a │ │ a │ │
│ x │ y │ z │ │ x │ y │ z │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
0 1 2 3 4 5 6 7 8
The
next example uses #pragma pack(1) to set the alignment of unions
of type uu to 1 byte: #pragma pack(1)
union uu {
short a;
struct {
char x;
char y;
char z;
} b;
};
union uu pack_array[2];
┌─── packed[0] ───┬─── packed[1] ───┐
│ │ │
│ a │ │ a │ │
│ x │ y │ z │ x │ y │ z │
└─────┴─────┴─────┴─────┴─────┴─────┘
0 1 2 3 4 5 6
The following examples show the results of the differences in the semantics of this pragma depending on whether -qpack_semantic=ibm or -qpack_semantic=ibm is in effect.
#pragma pack(1)
#pragma pack(push) // ignored when -qpack_semantic=ibm is in effect
#pragma pack(push,2) // ignored when -qpack_semantic=ibm is in effect
struct s_t {
char a;
int b;
} S;
With -qpack_semantic=gnu in effect, the packing
value in effect when the structure S is declared
is 2, and the structure is aligned on 2-byte boundaries. With -qpack_semantic=ibm in
effect, the second two directives are ignored, and the packing value
in effect for structure S is 1, and it is aligned
on 1-byte boundaries.#pragma pack(push,1) // ignored when -qpack_semantic=ibm is in effect
#pragma pack(push,4) // ignored when -qpack_semantic=ibm is in effect
#pragma pack(2)
#pragma pack(pop)
#pragma pack(pop)
#pragma pack(pop)
struct s_t {
char a;
int b;
} S;
With -qpack_semantic=gnu in effect, since pop only
pops values that have been pushed onto the stack with a push directive,
the first pop directive pops 4 off the stack, the second one
pops 1 off the stack, and the alignment is the setting in effect at
the beginning of the compilation unit (the intervening #pragma
pack(2) directive is overridden). With -qpack_semantic=ibm in
effect, the pop statement pops the value 2 off the stack, and
the alignment is the setting in effect at the beginning of the compilation
unit. struct s_t {
char a;
int b;
#pragma pack(1)
struct t_t {
char x;
int y;
}T;
char c;
#pragma pack(2)
#pragma pack(1)
int d;
#pragma align(natural) \\ this only affects u_t.
#pragma pack(2) \\ this only affects u_t.
struct u_t {
char j;
int k;
}U;
}S;
When -qpack_semantic=gnu is in effect, the first #pragma
pack(1) directive applies to both structure t_t and s_t.
With -qpack_semantic=ibm the first #pragma pack(1) directive
applies to structure t_t only.