#pragma pack ディレクティブは、そのディレクティブの後に続く構造体のメンバーの位置合わせ規則を変更します。
>>-#--pragma--pack--(--+--------+--)--------------------------->< +-nopack-+ +-1------+ +-2------+ +-4------+ +-8------+ +-16-----+ '-pop----'
ここで、
1 | 2 | 4 | 8 | 16 | 構造体のメンバーは指定されたバイト位置合わせか自然な位置合わせの境界のうち、いずれか少ない方に位置合わせされ、指定された値はスタックにプッシュされます。 |
nopack | パッキングは適用されず、パック・スタックに nopack がプッシュされます。 |
pop | プラグマ・パック・スタックの一番上のエレメントがポップされます。 |
(引数が指定されていません) | #pragma pack() を指定した場合、#pragma pack(pop) を指定したのと同じ効果があります。 |
#pragma pack ディレクティブは、このディレクティブの後に続く宣言を持つ構造体のメンバーのみに適用される現行の位置合わせ規則を変更します。 これにより、構造体の位置合わせに直接、影響することはありませんが、 構造体のメンバーの位置合わせに影響することで、 位置合わせ規則に従って、構造体全体の位置合わせに影響する場合があります。
#pragma pack ディレクティブでは、 メンバーの位置合わせを強化することはできず、 むしろ位置合わせを低下させる可能性があります。 例えば、 整数データ型 (int) のメンバーの場合、#pragma pack(2) ディレクティブでは、 当該メンバーは構造体内で 2 バイト境界でパックされますが、#pragma pack(4) ディレクティブでは有効ではありません。
#pragma pack ディレクティブは、スタックをベースにしています。 すべてのパック値は、 ソース・コードの構文解析時にスタックにプッシュされます。 現行のプラグマ・パック・スタックの一番上にある値が、 現行の位置合わせ規則のスコープ内の後続のすべての構造体のメンバーをパックするために使用されます。
#pragma pack スタックは、 位置合わせ規則スタック内の現行エレメントに関連付けられます。 位置合わせ規則は、-qalign コンパイラー・オプションまたは #pragma options align ディレクティブで指定します。 新しい位置合わせ規則が指定されると、新規の #pragma pack スタックが作成されます。現行の位置合わせ規則がポップ位置合わせ規則スタックからポップすると、現行の #pragma pack スタックが空になり、前の #pragma pack スタックが復元されます。スタック操作 (パック設定のプッシュおよびポップ) は、 現行の #pragma pack スタックにのみ影響します。
#pragma pack ディレクティブ ビット・フィールドにビット・フィールド・コンテナーの境界をクロスさせます。
struct s_t1 { char a; int b; #pragma pack(1) struct s_t2 { char x; int y; } S2; char c; int d; } S1;
struct s_t { char a; int b; short c; int d; }S;
デフォルト・マッピング: | #pragma pack(1): |
---|---|
sizeof s_t = 16 | sizeof s_t = 11 |
offsetof a = 0 | offsetof a = 0 |
offsetof b = 4 | offsetof b = 1 |
offsetof c = 8 | offsetof c = 5 |
offsetof d = 12 | offsetof d = 7 |
align of a = 1 | align of a = 1 |
align of b = 4 | align of b = 1 |
align of c = 2 | align of c = 1 |
align of d = 4 | align of d = 1 |
関連情報