pack pragma

構造体メンバー、共用体メンバー、およびクラス メンバーのパッキング アラインメントを指定します。

構文

#pragma pack( show )
#pragma pack( push [ ,identifier ] [ ,n ] )
#pragma pack( pop [ , { identifier | n } ] )
#pragma pack( [ n ] )

パラメーター

show
(省略可能) パッキング アラインメントの現在のバイト値を表示します。 値は警告メッセージによって表示されます。

push
(オプション) 現在のパッキング アラインメント値を内部コンパイラ スタックにプッシュし、現在のパッキング アラインメント値を n に設定します。 n が指定されていない場合、現在のパッキング アラインメントの値がプッシュされます。

pop
(省略可能) 内部コンパイラ スタックの最上部からレコードを削除します。 npop で指定されていない場合、スタックの最上位の結果のレコードに関連付けられているパッキング値は、新しいパッキング アラインメント値になります。 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 が参照された後の最初の structunion、または class 宣言で有効になります。 pack は定義には影響しません。 引数なしの pack を呼び出すと、n/Zp コンパイラ オプションに設定された値に設定されます。 コンパイラ オプションが設定されていない場合、x86、ARM、および ARM64 の既定値は 8 です。 x64 ネイティブおよびARM64ECの既定値は 16 です。

構造体のアラインメントを変更した場合、メモリ内で使用されている領域が使用できなくなる可能性があります。 ただし、不均等なアクセスでは、パフォーマンスが低下したり、ハードウェアによって生成された例外が発生したりする可能性があります。 この例外動作は、SetErrorMode を使用して変更できます。

アラインメントの変更方法の詳細については、次の記事を参照してください。

  • alignof

  • align

  • __unaligned

  • x64 構造体の配置の例

    警告

    Visual Studio 2015 以降では、alignas 演算子と alignof 演算子を使用できます。これは、__alignof__declspec( align ) がコンパイラ間で移植できるのとは異なります。 C++ 標準はパッキングに対応していないため、ターゲット アーキテクチャのワード サイズ未満であるアラインメントを指定するには、まだ pack (または他のコンパイラでの対応する拡張機能) を使用する必要があります。

次のサンプルでは、packpragma を使用して、構造体のアラインメントを変更する方法を示します。

// 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

次の例では、pushpopshow の各構文を使用する方法を示します。

// 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

関連項目

pragma ディレクティブと __pragma および _Pragma キーワード