#pragma pack

Category

Object code control

Purpose

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.

Syntax

Read syntax diagramSkip visual syntax diagram
Default #pragma pack syntax  (-qpack_semantic=ibm in effect)

>>-#--pragma--pack--(--+--------+--)---------------------------><
                       +-nopack-+      
                       +-number-+      
                       '-pop----'      

Read syntax diagramSkip visual syntax diagram
#pragma pack syntax with -qpack_semantic=gnu in effect

>>-#--pragma--pack--(--+-----------------------------+--)------><
                       +-number--push--+-----------+-+      
                       |               '-,--number-' |      
                       '-pop-------------------------'      

Defaults

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).

Parameters

nopack
Disables packing. Note that this parameter is not recognized when -qpack_semantic=gnu is in effect; a warning message is issued and the pragma is ignored.
push
When specified without a number, pushes whatever value is currently in effect to the top of the packing "stack". When used with a number, pushes that value to the top of the packing stack, and sets the packing value to that of number for structures that follow. Note that this parameter is not recognized when -qpack_semantic=ibm is in effect; a warning message is issued and the pragma is ignored.
number
is one of the following:
1
Aligns structure members on 1-byte boundaries, or on their natural alignment boundary, whichever is less.
2
Aligns structure members on 2-byte boundaries, or on their natural alignment boundary, whichever is less.
4
Aligns structure members on 4-byte boundaries, or on their natural alignment boundary, whichever is less.
8
Aligns structure members on 8-byte boundaries, or on their natural alignment boundary, whichever is less.
16
Aligns structure members on 16-byte boundaries, or on their natural alignment boundary, whichever is less.
pop
When -qpack_semantic=ibm is in effect, sets the packing rule to that which was in effect before the current setting. When -qpack_semantic=gnu is in effect, pops the value specified in the last push statement off the stack and resets the current packing value to the value on the top of the stack, overriding any intervening value that may have been specified without a push statement.
Specifying #pragma pack() with no parameters (that is, with empty parentheses) has the following effect:
  • Disables all packing (equivalent to specifying #pragma pack(nopack)), when -qpack_semantic=ibm is in effect.
  • Sets the current packing value to that which was in effect at the beginning of the compilation unit, when -qpack_semantic=gnu is in effect.

Usage

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.

The #pragma pack directive causes bit fields to cross bit field container boundaries.
#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
The #pragma pack directive applies only to complete declarations of structures or unions; this excludes forward declarations, in which member lists are not specified. For example, in the following code fragment, the alignment for struct S is 4, since this is the rule in effect when the member list is declared:
#pragma pack(1)
struct S;
#pragma pack(4)
struct S { int i, j, k; };
A nested structure has the alignment that precedes its declaration, not the alignment of the structure in which it is contained, as shown in the following example:
#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.

Examples

The following example shows how the #pragma pack directive can be used to set the alignment of a structure definition:
//  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
This example shows how a #pragma pack directive can affect the size and mapping of a structure:
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
The following example defines a union uu containing a structure as one of its members, and declares an array of 2 unions of type uu:
          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];
Now, each union in the array packed has a length of only 3 bytes, as opposed to the 4 bytes of the previous case:
         ┌─── 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.

This example shows the effect of specifying the push parameter:
#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.
This example shows the effect of specifying the push and pop parameters together:
#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.
The following example shows the effect of specifying the directive inside a nested structure:
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.

Related information