sizeof
演算子が構造体のメンバーの合計サイズよりも大きいサイズを構造体に対して返すのはなぜですか?
ベストアンサー1
これは、配置制約を満たすためにパディングが追加されたためです。データ構造のアライメントプログラムのパフォーマンスと正確性の両方に影響します。
- 不整合アクセスはハード エラーになる可能性があります (多くの場合
SIGBUS
)。 - 不整合アクセスはソフト エラーになる可能性があります。
- ハードウェアで修正すると、パフォーマンスが若干低下します。
- または、ソフトウェアのエミュレーションによって修正されますが、パフォーマンスが大幅に低下します。
- さらに、原子性やその他の同時実行性の保証が破られ、微妙なエラーが発生する可能性があります。
以下は、x86 プロセッサの一般的な設定を使用した例です (すべて 32 ビット モードと 64 ビット モードを使用)。
struct X
{
short s; /* 2 bytes */
/* 2 padding bytes */
int i; /* 4 bytes */
char c; /* 1 byte */
/* 3 padding bytes */
};
struct Y
{
int i; /* 4 bytes */
char c; /* 1 byte */
/* 1 padding byte */
short s; /* 2 bytes */
};
struct Z
{
int i; /* 4 bytes */
short s; /* 2 bytes */
char c; /* 1 byte */
/* 1 padding byte */
};
const int sizeX = sizeof(struct X); /* = 12 */
const int sizeY = sizeof(struct Y); /* = 8 */
const int sizeZ = sizeof(struct Z); /* = 8 */
メンバーをアライメントでソートすることで、構造体のサイズを最小限に抑えることができます (基本型ではサイズでソートするだけで十分です) (Z
上記の例の構造体のように)。
重要な注意: C および C++ 標準では、構造体のアラインメントは実装定義であると規定されています。したがって、各コンパイラは異なる方法でデータをアラインメントすることを選択する可能性があり、その結果、異なる互換性のないデータ レイアウトが生まれます。このため、異なるコンパイラで使用されるライブラリを扱う場合、コンパイラがデータをどのようにアラインメントするかを理解することが重要です。一部のコンパイラには、#pragma
構造体のアラインメント設定を変更するためのコマンド ライン設定や特別なステートメントがあります。