pack
pragma
構造体メンバー、共用体メンバー、およびクラス メンバーのパッキング アラインメントを指定します。
構文
#pragma pack( show )
#pragma pack( push
[,
identifier
] [,
n
])
#pragma pack( pop
[,
{identifier
|n
} ])
#pragma pack(
[n
])
パラメーター
show
(省略可能) パッキング アラインメントの現在のバイト値を表示します。 値は警告メッセージによって表示されます。
push
(オプション) 現在のパッキング アラインメント値を内部コンパイラ スタックにプッシュし、現在のパッキング アラインメント値を n に設定します。 n が指定されていない場合、現在のパッキング アラインメントの値がプッシュされます。
pop
(省略可能) 内部コンパイラ スタックの最上部からレコードを削除します。 n が pop
で指定されていない場合、スタックの最上位の結果のレコードに関連付けられているパッキング値は、新しいパッキング アラインメント値になります。 n が指定されている場合、たとえば #pragma pack(pop, 16)
では、n が新しいパッキング アラインメント値になります。 identifier
を使用するポップの場合、#pragma pack(pop, r1)
の後、スタック内のすべてのレコードが identifier
のあるレコードまでポップされます。 そのレコードがポップされ、スタックの一番上にあるレコードに関連付けられたパッキング値が新しいパッキング アラインメント値になります。 スタック内のどのレコードにもない identifier
を使用してポップすると、pop
は無視されます。
ステートメント #pragma pack (pop, r1, 2)
は、#pragma pack (pop, r1)
に #pragma pack(2)
を付けたものと同じです。
identifier
(省略可能) push
と共に使用した場合、内部コンパイラ スタックのレコードに名前を割り当てます。 pop
と一緒に使用すると、identifier
が削除されるまで、内部スタックからレコードがポップオフされます。 identifier
が内部スタックで見つからない場合は、何もポップされません。
n
(省略可能) パッキングに使用される値 (バイト単位) を指定します。 コンパイラ オプション /Zp
がモジュールに設定されていない場合、n
の既定値は 8 になります。 有効値は 1、2、4、8、および 16 です。 メンバーのアラインメントは、n
の倍数またはメンバーのサイズの倍数の小さい方の境界上にあります。
解説
クラスを pack するには、そのメンバーをメモリ内で互いの直後に配置します。 一部またはすべてのメンバーを、ターゲット アーキテクチャの既定の配置よりも小さい境界に配置できることを意味します。 pack
では、データ宣言レベルで制御できます。 モジュール レベルの制御のみを提供するコンパイラ オプション /Zp
とは異なります。 pack は、pragma が参照された後の最初の struct
、union
、または class
宣言で有効になります。 pack
は定義には影響しません。 引数なしの pack
を呼び出すと、n
が /Zp
コンパイラ オプションに設定された値に設定されます。 コンパイラ オプションが設定されていない場合、x86、ARM、および ARM64 の既定値は 8 です。 x64 ネイティブおよびARM64ECの既定値は 16 です。
構造体のアラインメントを変更した場合、メモリ内で使用されている領域が使用できなくなる可能性があります。 ただし、不均等なアクセスでは、パフォーマンスが低下したり、ハードウェアによって生成された例外が発生したりする可能性があります。 この例外動作は、SetErrorMode
を使用して変更できます。
アラインメントの変更方法の詳細については、次の記事を参照してください。
-
警告
Visual Studio 2015 以降では、
alignas
演算子とalignof
演算子を使用できます。これは、__alignof
と__declspec( align )
がコンパイラ間で移植できるのとは異なります。 C++ 標準はパッキングに対応していないため、ターゲット アーキテクチャのワード サイズ未満であるアラインメントを指定するには、まだpack
(または他のコンパイラでの対応する拡張機能) を使用する必要があります。
例
次のサンプルでは、pack
pragma を使用して、構造体のアラインメントを変更する方法を示します。
// pragma_directives_pack.cpp
#include <stddef.h>
#include <stdio.h>
struct S {
int i; // size 4
short j; // size 2
double k; // size 8
};
#pragma pack(2)
struct T {
int i;
short j;
double k;
};
int main() {
printf("%zu ", offsetof(S, i));
printf("%zu ", offsetof(S, j));
printf("%zu\n", offsetof(S, k));
printf("%zu ", offsetof(T, i));
printf("%zu ", offsetof(T, j));
printf("%zu\n", offsetof(T, k));
}
0 4 8
0 4 6
次の例では、push、pop、show の各構文を使用する方法を示します。
// pragma_directives_pack_2.cpp
// compile with: /W1 /c
#pragma pack() // n defaults to 8; equivalent to /Zp8
#pragma pack(show) // C4810
#pragma pack(4) // n = 4
#pragma pack(show) // C4810
#pragma pack(push, r1, 16) // n = 16, pushed to stack
#pragma pack(show) // C4810
// pop to the identifier and then set
// the value of the current packing alignment:
#pragma pack(pop, r1, 2) // n = 2 , stack popped
#pragma pack(show) // C4810