【C言語】構造体を作る上でのアライメントのお話。そもそもアライメントとは…

C言語アライメントのお話












こんにちは,ちゆりです。

今回は上司に

上司
構造体を作る上ではアライメントを意識しなきゃダメでしょ。自分本位に欲しい物だけを詰めた構造体を作ってはダメよ。ダメダメ。

と指摘され,C言語におけるアライメントについて考えるいい機会になった。

アライメントとは

そもそもアライメントとは何なの。状態の僕でありましたが,せめて意味ぐらいは知っておこうと思い,辞書を引き英語の意味を調べてみました。

アライメント・・・「並べる,整列,比較,調整」などの意味で使われる。

だがしかし,今回はこんなことはどうでも良いのだ。

C言語におけるアライメントとは

まぁ。「アライメント」という意味的に何かを調整してくれるのだろう。
構造体を例に説明するとわかりやすいです。

例えばこんな構造体があったとしましょう。

  typedef struct
  {
    int int1;
    double double1;
    char char1;
    double double2;
  }STRUCT1;

そしてこの構造体をsizeof演算子でサイズを見てみるといくつになるでしょうか。
(ちなみに,僕の環境はsizeof(int)4バイト,sizeof(char)1バイト,sizeof(double)が,8バイトでした。)

じゃ,もう簡単ですね。

int + double + char + double = 4 + 8 + 1 + 8 = 21バイト

残念。不正解です。21バイトとはなりませんでした。
僕の環境では,なぜか24バイトとなりました。(環境によって異なる場合があります。)

では,どうしてこうなってしまうのか。実験していきましょう。

アライメントの計算

サクッとサンプル関数を作っていきます。

#include <stdio.h>
#include <stdint.h>

typedef struct
{
  int int1;
  double double1;
  char char1;
  double double2;
}STRUCT1;

int main()
{
  STRUCT1 st1;
  printf("st1 size=%d\n", sizeof(STRUCT1));

  printf("st1     %p\n", &st1);
  printf("int1    %p\n", &st1.int1);
  printf("double1 %p\n", &st1.double1);
  printf("char1   %p\n", &st1.char1);
  printf("double2 %p\n", &st1.double2);

  return 0;
}

僕の環境では,以下の結果となりました。

st1 size=24
st1      0x7ffacad0
int1     0x7ffacad0
double1  0x7ffacad4
char1    0x7ffacadc
double2  0x7ffacae0

intは4byte,doubleは8byte,そしてcharにも4byteのアドレスが割り当てられているように見えますね。

charが1バイトのはずが4バイトとなっているために構造体サイズが24バイトとなっていました。

この理由は,CPUの都合によって,コンパイラが適当に境界調整(アライメント)を行い,構造体にパディングを挿入しているからなのです。

パディングとは

僕の環境ではintdoubleは4の倍数のアドレスに配置されるようで,charも4の倍数のアドレスに格納され,4バイト ー char(1バイト) = 3バイトがパディングされていたようです。

構造体アライメント
構造体パディング図

どうしてパディングされるのか

どうしてパディングされるのかイマイチピンときませんが…

(構造体の)サイズが小さい方が良くない??
パディングによって構造体アクセスに影響があるのでは??

なんて思ってましたけど,パディングされるのにもワケがあるのでしょう。そのワケとは..?

CPUのメモリへのアクセス高速化なんです。
高速化の仕組みについては今回割愛しますが…

奇数よりも偶数で,かつ,4バイト区切りで構造体を作成しなさい。というアドバイスです。
それを,意識すれば「お。こいつC言語分かっているな。」と一目置かれるでしょう(多分…)

最後に

構造体を作成する上で,特にchar型なんかは配列で作成すると思いますが,char[110]という配列よりもchar[120]という配列のほうがセンスが良いです。たとえ,配列に100文字しか格納されないとしても,4の倍数で多めに配列を取ってあげましょう。

ちなみに

パディングの関係で以下2つの構造体のサイズは一緒になります。

typedef struct
{
  int int1;
  double double1;
  char char1;
  double double2;
}STRUCT1;

typedef struct
{
  int int2;
  double double3;
  char char2[4];
  double double4;
}STRUCT2;


なので,パディングを意識しないと予期しない構造体サイズになっていたなんてこともあり得ますね。

C言語おすすめ書籍

僕のC言語のおすすめ書籍を紹介しておきます。難易度はやや高めなので入門書として購入するのはあまりおすすめできませんが,C言語をある程度勉強された方には非常にタメになる一冊です。これさえ理解できれば怖いものなしです。ぜひ。

 

★次に読んでほしい記事

【C言語】fopenしたならfcloseを忘れずにしっかりやりなさい。しないとどうなるのよ。

2019年9月1日












★人気の記事一覧

合法的に女の子に精液の匂いを嗅がせる方法

【精子を食べる!?】食ザーが理にかなっているというお話

[Froala Design Blocks ]無料でオシャレなサイト作成ができるHTMLのテンプレート

スムージーは本当に健康に効果があるのか化学の観点でのみ考えてみる

気に入ったらLet's Share!!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ABOUTこの記事をかいた人

ちゆり

6年間化学を専攻していたのになぜか一部上場のIT企業のエンジニアへ。脱サラ田舎暮らしに憧れ,なんだかんだプログラミングが好き。口癖は仕事辞めたい。凡人にはなりたくない凡人。