構造メモリの配置規則
1.構造メモリアライメントとは
構造は配列のようなものではありません。さまざまなタイプのデータを構造に格納できます。そのサイズは、単に各データメンバーのサイズの合計ではありません。メモリの読み取り要件に制限されますが、各メンバーのメモリへの格納は、それは特定のオフセットで格納されます。さまざまなタイプに応じて、各メンバーは特定の配置番号に従って配置および格納される必要があります。最後に、構造全体のサイズは特定の配置番号に従って配置される必要があります。
第二に、配置のルール
- 最初のメンバーは、構造体変数からのオフセットが0のアドレスにあります。
- その他のメンバー変数は、アラインメント番号の整数倍のアドレスにアラインする必要があります(アラインメント番号=コンパイラーのデフォルトのアラインメント番号とメンバーサイズの小さい方の値)。
- Linuxのデフォルトは4、vsのデフォルトは8です。
- 構造体の合計サイズは、最大整列数の整数倍です(最初のメンバーを除く各メンバー変数には整列数があります)。
構造がネストされている場合、ネストされた構造はその最大整列数の整数倍に整列され、構造の全体のサイズはすべての最大整列数の整数倍になります(ネストされた構造の整列数を含む)。
特徴:
- 各メンバーのオフセット%独自の線形番号= 0
- 構造の全体的なサイズ%すべてのメンバーの最大配置= 0
- 構造体のアラインメント番号は、自身のメンバーのアラインメント番号の中で最大のアラインメント番号です
3.例
// 平台VS2013下(默认对齐数为8)
// 案例一
struct S1
{
char c1;
int i;
short s2;
};
printf("%d\n", sizeof(struct S1)); // 12
// 案例二
struct S2
{
char c1;
short s2;
int i;
};
printf("%d\n", sizeof(struct S2)); // 8
ケースワン分析
char型は1バイトを占め、コンパイラのデフォルトのアライメント番号は8で、変数のアライメント番号は1、実際のオフセットは0です
。int型は4バイトを占め、コンパイラのデフォルトのアライメント番号は8で、その後変数のアライメント
数字4、オフセットは4の倍数である必要があります。実際のオフセットは4バイトのshort型で2バイトを占め、コンパイラーのデフォルトのアライメント番号は8、変数アライメント番号2、オフセットは2の倍数である必要があります実際のオフセットは8です。
構造体の全体の配置番号はすべてのメンバーの中で最大です。配置番号は4
の構造体の全体のサイズです。上記のデータが占めるスペースのサイズに応じて、構造体のサイズは10バイトと計算されます。
配置規則に従って、4の倍数に配置する必要があります。実際のサイズは12バイトです。
ケース2の分析
char型は1バイトを占め、コンパイラのデフォルトのアライメント番号は8、変数のアライメント番号は1、実際のオフセットは0、
short型は2バイトを占め、コンパイラのデフォルトのアライメント番号は8、そして変数のアライメント数値2、オフセットは2の倍数である必要があります。実際のオフセットは2
int型で4バイトを占有します。コンパイラのデフォルトの配置番号は8で、変数は数字4に配置されます。オフセットは4の倍数である必要があります実際のオフセットは4
です。構造の全体のアライメント番号は、すべてのメンバーの中で最大です。アライメント番号 は、4
構造の全体のサイズです。上記のデータが占めるスペースのサイズに応じて、構造のサイズは8バイトです。
配置規則に従って、4の倍数に配置する必要があります。実際のサイズは8バイトです。
グラフィカル分析
第4に、メモリアラインメントがある理由
プラットフォームの移植性が良い
すべてのハードウェアプラットフォームが任意のアドレスのデータにアクセスできるわけではありません。一部のハードウェアプラットフォームは、特定のアドレスの特定のタイプのデータにしかアクセスできません。そうでない場合、ハードウェア例外がスローされ、境界が揃っていない境界は直接関与しません。データを読み取ります。
高いCPU処理効率
上の図からわかるように、2つのストレージ方法に対応して、CPUの読み取り粒度が4バイトの場合、
- 次に、int型の場合、メモリアライメントに従って格納されている場合、プロセッサは4バイトを読み取るためにメモリに一度アクセスするだけで済みます。
- 上の図に示すように、メモリに従って読み取られない場合、完全なint型変数を読み取るには、メモリに2回アクセスする必要があります。
- 具体的なプロセスは次のとおりです。最初に4バイトを取り出し、最初のバイトを破棄し、2回目に4バイトを取り出し、最後の3バイトを破棄して、完全なintデータをつなぎます。 。