#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 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします)
num:C_Compat は、クラス・レイアウトが XL C コンパイラーによって生成されるレイアウトとの互換性を持つように、構造体メンバーを位置合わせします。これは、次の場合に適用されます。- #pragma pack(1) または #pragma pack(2) により保護されているクラス・レイアウトがある場合。
- クラス・データ・メンバーが、#pragma pack(1) または #pragma pack(2) により定義された範囲を超えた位置合わせが行われているビット・フィールドを含んでいる場合。
- ビット・フィールドのビット長が、そのビット・フィールド・タイプに含めることができる最大数を超えている。
- packed
- 1 バイトの境界、または自然の位置合わせ境界の、どちらか小さいほうに構造体メンバーを位置合わせします。これは、#pragma pack(1) と同じです。
- pop
- これは、#pragma pack によって追加された以前の値を除去します。
パラメーターなしで #pragma pack() を
指定することは、 #pragma
pack(pop) または #pragma pack(4) を
指定することと同じです。
注: パラメーターなしで #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
size of struct A = 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
};
インライン化された関数で定義された構造体の中に、複数の #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
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 |
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[0] ───┬─── packed[1] ───┐ │ │ │ │ a │ │ a │ │ │ x │ y │ z │ x │ y │ z │ |─────┴─────┴─────┴─────┴─────┴─────┘ 0 1 2 3 4 5 6