C言語のアライメントに関して本当に理解してやっている人はいるんですか?
理解してる人はたくさんいると思いますよ。
理解力が低い私にはとてもじゃないけど理解できない記事でした
そう言われれば、プログラマが理解していなくてもそれほど困らない事かもしれませんね。なぜならアラインするのはCコンパイラですから。プログラマが知らない間にコンパイラは全ての変数を適切にアラインしてくれています。あなたがアラインメントを知らないばかりにプログラムが動かなかった、なんてことはなかったはずです。まずはご安心を。
でも時々、コンパイラがどうアラインするか、意識することがあります。それは構造体を使う時です。次のコードをコンパイルして動かしてみてください。
C
1#include <stdio.h>
2#include <stdint.h>
3//#pragma pack(4) // <= 試せるなら
4
5struct A {
6 double d; // 8
7 float f; // 4
8 int32_t a; // 4
9 int16_t b; // 2
10 int16_t c; // 2
11};
12struct B {
13 int32_t a;
14 double d;
15 int16_t b;
16 float f;
17 int16_t c;
18};
19
20int main(void)
21{
22 printf("A: %ld bytes.\n", sizeof(struct A));
23 printf("B: %ld bytes.\n", sizeof(struct B));
24 return 0;
25}
struct A と struct B はどちらも同じメンバ変数を持っていますが、並べた順序が違います。私の手元で実行すると、結果はこうでした。
bash
1# ./a.exe
2A: 24 bytes.
3B: 32 bytes.
もしアラインメントが一切無いなら両方同じバイト数になりますが、そうはならない。メンバ変数の並びが違うので、それぞれのメンバをアラインした結果、 struct B には struct A よりも隙間が多くなったのです。
質問者もお手元で確かめてください。
私の場合、違いは8バイトです。構造体一個のサイズが8バイト違っても大勢に影響は無いでしょう。なにせ今時のパソコンはGBオーダーのメモリを積んでますから。
でも構造体を配列にしたら、その差は拡大します。例えば要素数1000の配列なら、違いは8000バイトです。それだけメモリが無駄になってしまいます。組込みの世界では今だってメモリサイズの制約が大きいので、こうしたことに敏感です。
構造体のメンバ変数は、プログラマが書いた通りに配置されます(Cコンパイラはメンバ変数の順序を変えない)ので、ここの順序はプログラマの責任です。気にするのは当然でしょう。
「2バイト整数は2の倍数のアドレスに配置・アラインさせる」という記述は何ですか?
上のコードには int16_t 型のメンバ変数 b, c を含めました。b, c は2の倍数アドレスにアラインされるので二つ続けて並べれば、隙間なく配置できる=隙間を減らせるというわけです。
念のため繰り返しますが、アラインメントを理解できなくてもCプログラムを動かすことに大きな支障はないと思いますし、気にしなくて済む分野のソフトウェアはいくらでもあります。