#pragma pack

カテゴリー

オブジェクト・コード制御

目的

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

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

構文

構文図を読む構文図をスキップする
 デフォルトの #pragma pack 構文 

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

デフォルト

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

パラメーター

nopack
パッキングを使用不可にします。警告メッセージが出され、プラグマが無視されます。
number
以下のいずれかです。
1
1 バイトの境界上または自然な位置合わせの境界上のどちらか小さい方に、構造体メンバーを位置合わせします。
2
2 バイトの境界上または自然な位置合わせの境界上のどちらか小さい方に、構造体メンバーを位置合わせします。
4
4 バイトの境界上または自然な位置合わせの境界上のどちらか小さい方に、構造体メンバーを位置合わせします。
8
8 バイトの境界上または自然な位置合わせの境界上のどちらか小さい方に、構造体メンバーを位置合わせします。
16
16 バイトの境界上または自然な位置合わせの境界上のどちらか小さい方に、構造体メンバーを位置合わせします。
pop
#pragma pack によって追加された前の値を削除します。パラメーターなしで #pragma pack() を指定することは、pop と同等です。

使用法

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

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

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

#pragma pack ディレクティブは、1 ビット境界上の構造体/共用体のすべてのビット・フィールドの位置合わせを行います例:
#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 ディレクティブは、構造体または共用体の完全な宣言にのみ適用されます。ただし、メンバー・リストが指定されないフォワード宣言は除きます。例えば、以下のコード・フラグメントでは、 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(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
この例は、#pragma pack ディレクティブが構造体のサイズとマッピングにどのような影響を与えるかを示したものです。
struct s_t {
	char a;
	int b;
	short c;
	int d;
}S;
デフォルト・マッピング: #pragma pack(1):
s_t のサイズは 16 s_t のサイズは 11
a のオフセットは 0 a のオフセットは 0
b のオフセットは 4 b のオフセットは 1
c のオフセットは 8 c のオフセットは 5
d のオフセットは 12 d のオフセットは 7
a の位置合わせは 1 a の位置合わせは 1
b の位置あわせは 4 b の位置合わせは 1
c の位置合わせは 2 c の位置合わせは 1
d の位置合わせは 4 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

関連情報