sizeof();
この構造体の が 16 バイトなのはなぜですか? 私はg ++でコンパイルしています。
struct bitmapfileheader {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};
sizeof();
この構造体の が 16 バイトなのはなぜですか? 私はg ++でコンパイルしています。
struct bitmapfileheader {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};
これは、4バイトのintが4バイトの境界に揃えられているため、bfTypeの後に2バイトのパディングがあるためです。
配置。 プラットフォームでは、intは4バイトに揃える必要があり、shortは2バイトに揃える必要があります。
+0 -1 : bfType
+2 -3 : <padding>
+4 -7: bfSize
+8 -9: bfReserve1
+10 -11: bfReserve2
+12 -15: bfOffBits
-------------
16 bytes
位置合わせされていない構造は多くのアーキテクチャで追加の作業を必要とするため、位置合わせは適切です。
構造内の個々のフィールドは、適切に配置する必要があります。コンパイラーは、アライメント要件を満たすために、構造体に追加のスペースを埋め込みます。
UNALIGNED
これが不要な場合は、マクロを使用できます。
あなたのコンパイラはフィールドに4バイトのアラインメントを使用していると思います。
この問題は、配置と呼ばれる概念が原因で発生します。多くの場合、数のバイト単位のサイズの倍数であるアドレスに数を配置することが望ましいです (最大値まで、多くの場合、プラットフォームのポインター サイズ)。そのように配置された変数は、n バイト境界に位置合わせされていると言われます。ここで、n数です。これの正確な効果は、プロセッサによって異なります。データが適切に配置されている場合、多くのプロセッサは計算を高速に実行します。不適切にアラインされたデータに対して操作 (場合によってはロード操作) を実行できないものもあります。このようなデータを操作するには、データを 2 つのレジスタにロードしてから、一連のビット シフトとマスクを実行して取得する必要があります。使用可能な値であり、元に戻す必要があります。int
単純に 1 つのバケツに全体を保管するのではなく、2 つのバケツのそれぞれに半分を保管し、それらを組み合わせて使用する必要があるようなものと考えてくださいint
。
あなたの場合、イニシャルbfType
は 2 バイト境界にbfSize
揃える必要がある可能性が高く、4 バイト境界に揃える必要がある可能性があります。コンパイラは、構造体全体を 4 バイトに揃え、 と の間bfType
に未使用の 2 バイトを残すことで、これに対応する必要がありbfSize
ます。
ただし、同じシステムでコンパイルする場合、おそらくコンパイラ オプションと使用される特定の ABI に応じて、パディングは一貫したものになるでしょう (通常、互換性をなくそうとしない限り、同じプラットフォームで安全です)。同じ最初の 5 つのメンバーを持つ別の構造体を自由に作成できます。それらは、まったく同じ位置で、他の構造体の 16 バイトを占有します。
この動作を本当に回避する必要がある場合は、コンパイラのドキュメントを確認する必要があります。ほとんどのコンパイラは、変数をアラインメントなしとして宣言する属性またはキーワードと、構造体にパディングがないことを示す別の属性またはキーワードを提供します。しかし、これらが一般的な過程で必要になることはめったにありません。
パディングを避けるために構造体をプラグマパックできます
ISO C++03、9.2[class.mem]/12:
access-specifier を介在させずに宣言された (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス指定子で区切られた非静的データ メンバの割り当て順序は規定されていません (11.1)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 (10.3) および仮想基本クラス (10.1) を管理するためのスペースの要件も同様です。
メモリが割り当てられる方法のため、短い後にパディングがあります
これはアライメントによるものです-コンパイラはパディングを行う必要があります。