#pragma pack

目的

すべての集合体メンバーの位置合わせを、指定されたバイト境界に設定します。

バイト境界の数値が、メンバーの自然の位置合わせより小さい場合、埋め込みバイトは除去され、それにより、構造体または共用体の全体のサイズは小さくなります。

構文

構文図を読む構文図をスキップする
>>-#--pragma--pack--(--+-number-------+--)---------------------><
                       +-full---------+      
                       +-num:C_Compat-+      
                       +-packed-------+      
                       +-pop----------+      
                       +-twobyte------+      
                       '-reset--------'      

デフォルト

集合体のメンバー (構造体、共用体、およびクラス) は、その自然境界に位置合わせされ、構造体はその自然境界で終わります。集合体の位置合わせは、その集合体の最も厳密なメンバー (最大の位置合わせ要件を持つメンバー) の位置合わせです。

パラメーター

number
次のいずれかです。
1
1 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。
2
2 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。
4
4 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。
8
今後使用するために予約済みです。
16
今後使用するために予約済みです。
full
4 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。これは、#pragma pack(4) と同じです。
num:C_Compat
num は次のいずれかです。
  • 1 (1 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします)
  • 2 (2 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします)
C++ のみの始まり
num:C_Compat は、クラス・レイアウトが XL C コンパイラーによって生成されるレイアウトとの互換性を持つように、構造体メンバーを位置合わせします。これは、次の場合に適用されます。
  • #pragma pack(1) または #pragma pack(2) により保護されているクラス・レイアウトがある場合。
  • クラス・データ・メンバーが、#pragma pack(1) または #pragma pack(2) により定義された範囲を超えた位置合わせが行われているビット・フィールドを含んでいる場合。
  • ビット・フィールドのビット長が、そのビット・フィールド・タイプに含めることができる最大数を超えている。
C++ のみの終わり
packed
1 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。これは、#pragma pack(1) と同じです。
pop
これは、#pragma pack によって追加された以前の値を除去します。 パラメーターなしで #pragma pack() を 指定することは、C++ のみ #pragma pack(pop)
C++ のみの終わり
または C のみ #pragma pack(4) C のみ を 指定することと同じです。
注: パラメーターなしで #pragma pack() を使用することは推奨されません。代わりに #pragma pack(4) を使用してください。
twobyte
2 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。これは、#pragma pack(2) と同じです。
reset
パッキング規則を、現在の設定より前に有効だった設定にします。

使用法

#pragma pack ディレクティブは、集合体型のインスタンスの宣言に対してではなく、集合体型の定義に対して適用されます。そのため、指定された型の宣言された変数すべてに自動的に適用されます。

#pragma pack ディレクティブは、このディレクティブの後に続く宣言を持つ構造体のメンバーのみに適用される現行の位置合わせ規則を変更します。 これにより、構造体の位置合わせに直接、影響することはありませんが、 構造体のメンバーの位置合わせに影響することで、 構造体全体の位置合わせに影響する場合があります。

#pragma pack ディレクティブでは、 メンバーの位置合わせを強化することはできず、 むしろ位置合わせを低下させる可能性があります。 例えば、短整数データ型のメンバーの場合、#pragma pack(1) ディレクティブでは、 当該メンバーは構造体内で 1 バイト境界でパックされますが、 #pragma pack(4) ディレクティブでは有効ではありません。

このプログラムをコンパイルして実行すると、出力は以下のようになります。
size of struct A = 6
#pragma pack ディレクティブを削除すると、以下のような出力になります。
size of struct A = 8
#pragma pack ディレクティブは、構造体や共用体の完全な宣言にのみ適用されます。このため、フォワード宣言は除外されます。フォワード宣言には、メンバー・リストが指定されていません。例えば、以下のコード・フラグメントにおいて、struct S の位置合わせは 4 です。これは、メンバー・リストが宣言される場合に有効な規則です。
#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
         };

インライン化された関数で定義された構造体の中に、複数の #pragma pack ディレクティブがあると、構造体の先頭にある、有効な #pragma pack ディレクティブが優先されます。

次は、構造体定義の位置合わせを設定するための #pragma pack ディレクティブの使い方の例です。
//  header file file.h

   #pragma pack(1)

   struct jeff{           //    this structure is packed 
     short bill;          //    along 1-byte boundaries    
     int *chris;
   };
   #pragma pack(reset)       //   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
この例では、どのように #pragma pack ディレクティブが構造体のサイズやマッピングに影響を及ぼすことができるかを示しています。
struct s_t {
	char a;
	int b;
	short c;
	int d;
}S;
デフォルトのマッピング #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
次の例は、そのメンバーの 1 つとして構造体を含む共用体 uu を定義し、型 uu の 2 つの共用体の配列を宣言しています。
          union uu {
            short    a;
            struct {
              char x;
              char y;
              char z;
            } b;
          };

          union uu nonpacked[2];
共用体メンバー間の最大の位置合わせ要件は short a の要件、すなわち、2 バイトです。この要件を強制するために、配列内の各共用体の終わりに 1 バイトの埋め込みが追加されます。
         ┌───── nonpacked[0] ─────────── nonpacked[1] ───┐
         │                       │                       │
         │     a     │           │     a     │           │
         │  x  │  y  │  z  │     │  x  │  y  │  z  │     │
         |─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
         0     1     2     3     4     5     6     7     8
次の例は、#pragma pack(1) を使用して、型 uu の共用体の位置合わせを 1 バイトに設定しています。
         #pragma pack(1)

          union uu {
            short    a;
            struct {
              char x;
              char y;
              char z;
            } b;
          };

          union uu pack_array[2];
これで、配列 packed 内の各共用体の長さは、前の場合の 4 バイトとは異なり、3 バイトになります。
         ┌─── packed[0] ───┬─── packed[1] ───┐
         │                 │                 │
         │     a     │     │     a     │     │
         │  x  │  y  │  z  │  x  │  y  │  z  │
         |─────┴─────┴─────┴─────┴─────┴─────┘
         0     1     2     3     4     5     6