その時凡人が動いた

凡人が凡人らしからぬことをするために日々奮闘するブログ

C言語の配列の仕組み

f:id:alex23drum:20140815184113j:plain

今回はC言語における「配列」の仕組みについて説明したいと思います。

配列とは

みなさんご存知だと思いますが一応。
配列とは 同じ型のデータを複数並べたもの です。
(C言語以外の配列は違う型も同じ配列に含めることができますが)

例えば、int a[10] と宣言された配列はint型の要素を10個持った配列となり、 i番目の要素には a[i - 1] でアクセスすることができます。(0番目から始まることに注意)

配列の正体

では、この配列の正体はなんなのでしょうか?なぜ a[i] と書けばaのi番目の要素を取り出すことができるのでしょうか?

c言語において、配列は 連続するメモリ領域に要素を並べたもの として定義され、配列の要素へのアクセスは 配列の先頭要素のメモリアドレスに要素のインデックスをオフセットとして加えたアドレス の値を参照することで行われます。くわしく見ていきましょう。

例えば、

int a[10];
for (int i = 0; i < 10; i++) {
  a[i] = i;
}

このように0 ~ 9の数字が格納された配列aがあったとします。 このとき、 a とは、 配列 a の先頭要素のアドレス を示します。

ここで、C言語では *aポインタaの指すアドレスの中身 を表すため、 a[0] 、すなわち配列の最初の要素は *a とも書けます。 では、a[1]は何を指しているのでしょうか?? さきほど 配列は連続するメモリ領域に要素を並べたもの と述べました。 すなわち、 配列aの要素a[1]が格納されているアドレスは、要素a[0]の次のアドレスとなっています。 例えば、a[0]のアドレスが1000だったとすると、a[1]は1001、a[2]は1002、、というように連続しています。

ここまで分かれば、配列のほとんどが分かったようなものです。 a[1]は何を指しているのでしょうか?? という答えは、 *(a + 1) を指しているというのが正解です。 a[2]なら *(a + 2) 、a[3]なら *(a + 3) ... という具合に、a[i]は *(a + i) を示しています。

このように、C言語では、本来ならば *(a + i) と書くべきところを、 メモリアドレスを指定するポインタを直接操作することは誤りの原因となることが多いという理由から、 a[i]と書けるようになっています。 すなわち、 a[i] = *(a + i) なので、i[a]と書いても同じ結果が得られます。(もちろん誤解を生む書き方なのでやめたほうがいいですが^^;)

ちなみに、このようにプログラムの意味としては同じものを、よりわかりやすい構文で書けるものを 糖衣構文 と言います。

以上です。お疲れ様でした!!