1

私は自分のプロジェクトでデータ構造を使用していますが、特定の構造のコンテキストでは、構造のパディングについて疑問があります。まず、以下の構造を見てください。Visual Studio 2008 コンパイラを使用しています。

typedef struct tagDATA_PACK
{
   DWORD dDataLength;
   BYTE bFlags;
   BYTE bAttrib;
   BYTE bOffset;
}DATA_PACK;

質問 1: 上記の構造のサイズはどのくらいですか? 8バイトを示しています。正しいです。しかし、

以下に示す変更された構造を検討してください。

typedef struct tagDATA_PACK
{
   DWORD dDataLength;
   BYTE bFlags;
}DATA_PACK;

ここでのサイズは、上記の 8 バイト構造と同じです。ここで私の疑問は、余分な 3 バイトを追加するコンパイラはどこにあるのでしょうか? BYTE bFlags の後ですか、それとも前ですか?

あなたのすべての答えは大歓迎です。

4

4 に答える 4

4

構造体とクラスの配置とパディングは、標準では指定されていません。それは完全にコンパイラにかかっています。ただし、正常なコンパイラはすべて、基盤となるプラットフォーム ABI に従います。あなたの場合、プラットフォームは Windows であり、Windows プラットフォームの ABI に準拠しています。

この場合のパディングは、両方の構造体で、最後のメンバーの後にあります。最初の構造体には追加のパディング バイトが 1 つあり、2 番目の構造体には追加のパディング バイトが 3 つあります。

構造体の最大の型のサイズは 4 です。これは、全体のサイズが 4 の倍数になることを意味します。どちらの構造体でも、構造体に対応する最小の 4 の倍数は 8 です。

各データ型には配置プロパティがあります。4 バイト データ型のアラインメントは 4 です。2 バイト データ型のアラインメントは 2 です。アラインメントが 4 の型は、構造体の先頭からの 4 バイト オフセットに配置するとアラインされます。アラインメントが 2 の型は、構造体の先頭から 2 バイトのオフセットに配置されるとアラインされます。等々。

メンバーは、メンバーの宣言の順序とメンバーの配置プロパティの両方を尊重する最小のオフセットに配置されます。

構造体の内部にパディングがある例については、この構造体を検討してください

struct MyStruct
{
   char c;
   int i;
};

のアラインメントcは 1 で、 のアラインメントiは 4 です。したがって、cは 1 バイト境界にi配置され、4 バイト境界に配置する必要があります。つまりc、オフセット 0 があり、3 つのパディング バイトがありi、オフセット 4 で配置されます。

于 2013-02-04T10:10:06.270 に答える
1

コンパイラが望むところならどこでも。それが重要な場合、とにかく移植性のないことをしているので、なぜそれが重要なのですか?

于 2013-02-04T10:10:58.803 に答える
1

コンパイラ次第という答えはすべて正しいですが、コンパイラ次第であるため言語仕様ではレイアウトにいくつかの制限があります。これらの制限は、C のすべての構造、C++03 の「プレーン オールド データ」(基本的には C の機能のみを使用することを意味します)、および C++11 の「標準レイアウト」構造 (コンストラクターとデストラクタを使用できます) に適用されます。制限事項は次のとおりです。

  • 構造体へのポインターを最初のメンバーの型に (再解釈) キャストすると、最初のメンバーへの有効なポインターが生成されます (C++11 §9.2/20)。これは、最初のメンバーの前にパディングができないことを意味します。
  • 共用体の 2 つの構造体が同じ初期部分 (同じ順序の同じ型のメンバー) を持ち、そのうちの 1 つを介して共用体が初期化される場合、これらの初期メンバーは他のものを介してアクセスされる可能性があります (C++11 §9.2/19 )。つまり、メンバー オフセットは、その前に宣言されたメンバーにのみ依存する可能性があります。

標準レイアウトへの制限は重要です。どちらも、基本クラスまたは仮想メンバーを持つクラスには当てはまりません。

メモリを無駄にしたくないという要望と組み合わせると、実際には 1 つの実用的なアルゴリズムしか残らないため、すべてのコンパイラで使用されます。これは、すべてのコンパイラが同じ入力に対して同じレイアウトを生成するという意味ではありません。これは、さまざまなプリミティブ型のサイズとアライメントの要件がプラットフォーム間で異なるためです。アルゴリズムは次のとおりです。

  • 最初の部材をオフセット 0 に配置します。
  • 後続の各メンバーを、必要な配置で割り切れる最初の使用可能なオフセットにレイアウトします。
  • 構造体のサイズを、任意のメンバーの最大アライメントの次の倍数に丸めます。
  • 構造の位置合わせ要件は、すべてのメンバーの最大の位置合わせです。

(MSVC++ の MSDN がこれをどこかに記述していることはほぼ確実ですが、すぐに見つけることができませんでした)

于 2013-02-04T10:48:49.290 に答える