著者:ファットセレナーデ
リンク:https://www.jianshu.com/p/4b36f865adb9
出典:Jianshu
目次
1. 構造調整の 3 つの原則
1. データメンバーの配置規則: 構造体 (または共用体) のデータメンバーは、オフセット 0 の位置に最初のデータメンバーが配置され、以降の各データメンバーの開始位置はそこから格納される必要があります。 member メンバーのサイズまたはサブメンバーのサイズ (メンバーに配列、構造体などのサブメンバーがある限り) は、整数の倍数から始まります (たとえば、int が 4 バイトの場合、整数倍でなければなりません) 4 の整数倍のアドレスから格納される)
2. メンバとしての構造体: 構造体内に構造体メンバが存在する場合、構造体メンバは内部の最大要素サイズの整数倍のアドレスから格納する必要があります (struct a には struct b が含まれ、b には char、int、 double およびその他の要素の場合、b は 8 の整数倍から格納される必要があります)
3. 仕上げ作業: 構造体の合計サイズ、つまり sizeof の結果は、その中の最大のメンバーの整数倍でなければならず、不足分は埋められなければなりません。
まず、さまざまなオペレーティング システムで各データ型が占めるビット数を見てみましょう。
2 つまたは 3 つの質問例
図の出力は 24 ですが、なぜ 24 なのでしょうか?
a は double 型で 8 バイトを占め、最初のメンバーであるため、開始値はオフセットが 0 である位置に対応します。また、8 バイトを占有するため、 a はオフセット 8 のアドレス空間に対応します。
b は char 型で、1 バイトを占有し、次のアドレス空間である 1 の整数倍にアライメントされます。
c は int 型で、4 バイトを占有し、4 の整数倍にアライメントされ、アライメント番号は 12、アドレス空間のオフセットは 4 です。
d は short 型で、2 バイトを占有し、2 の整数倍にアライメントされ、アライメント番号は 16、アドレス空間のオフセットは 2 です。
構造体の合計サイズは最大の内部メンバーの整数倍である必要があり、不足分を埋める必要があります。struct1 の最大のメンバーは double 型であるため、構造体の合計サイズは 8 の整数倍になります。 17 文字のセクションを占めるため、合計サイズは 24 バイトになるはずです
以下の出力を見てみましょう。
出力は16です。
に示すように
b は int 型で、4 バイトを占有し、4 の整数倍にアライメントされ、アライメント番号は 8、アドレス空間のオフセットは 4 です。
c は char 型で、1 バイトを占有し、次のアドレス空間である 1 の整数倍にアライメントされます。
d は short 型で、2 バイトを占有し、2 の整数倍にアライメントされ、アライメント番号は 14、アドレス空間のオフセットは 2 です。
メモリ アライメントの原則により、構造体の合計サイズは 16 バイトです。
では、構造体を入れ子にして使用することはできますか? 入れ子にして使用する場合、メモリはどのように計算すればよいでしょうか?
ここでの出力は何でしょうか? 計算してみましょう
に示すように
b は int 型で、4 バイトを占有し、4 の整数倍にアライメントされ、アライメント番号は 8、アドレス空間のオフセットは 4 です。
c は char 型で、1 バイトを占有し、次のアドレス空間である 1 の整数倍にアライメントされます。
d は short 型で、2 バイトを占有し、2 の整数倍にアライメントされ、アライメント番号は 14、アドレス空間のオフセットは 2 です。
e は int 型で、4 バイトを占有し、4 の整数倍にアライメントされ、アライメント番号は 16、アドレス空間のオフセットは 4 です。
struct1 は 24 バイト、double は 8 バイトを占めることが知られていますが、理由がわからない場合は、上記を読んでください。
メンバーとしての構造体: 構造体内にいくつかの構造体メンバーがある場合、構造体メンバーは内部の最大要素サイズの整数倍のアドレスから格納される必要があります (struct a には struct b が含まれ、b には char、int、Double が含まれ、他の要素の場合、b は 8 の整数倍で格納される必要があります)
したがって、struct1 は 8 の整数倍で格納される必要があります。
次に、struct1 は 24 バイトを占め、8 の整数倍にアライメントされ、アライメント番号は 24、アドレス空間のオフセットは 24 になります。
したがって、構造体の合計サイズは 48 バイトです
3. なぜメモリの調整が必要なのか
(1) 性能向上
メモリ使用量の観点から、アライメント後のメモリ割り当てコストがアライメントされていない場合に比べて増加する場合がありますが、その理由は何ですか?
データ構造 (特にスタック) は、可能な限り自然な境界上に整列する必要があります。整列されていないメモリにアクセスするには、プロセッサは 2 回のメモリ アクセスを行う必要がありますが、整列されたメモリ アクセスには 1 回のアクセスしか必要ありません。最も重要なことは、メモリ システムのパフォーマンスを向上させることです。
(2) クロスプラットフォーム
一部のハードウェア プラットフォームでは、どのアドレスのデータにもアクセスできず、特定の種類のデータのみを処理できます。それ以外の場合は、ハードウェア レベルでエラーが発生します。
一部の CPU (Alpha、IA-64、MIPS、SuperH アーキテクチャに基づくものなど) は、アライメントされていないデータの読み取りを拒否します。プログラムがこれらの CPU に整列されていないデータの読み取りを要求すると、CPU は例外処理状態に入り、実行を続行できないことをプログラムに通知します。
たとえば、ARM、MIPS、SH ハードウェア プラットフォームでは、オペレーティング システムがアライメントされていないデータへのアクセスを要求されると、デフォルトでアプリケーションにハードウェア例外がスローされます。したがって、コンパイラがメモリ アライメントを行わないと、多くのプラットフォームでの開発が困難になります。