C言語における「配列」とは、同じ型のデータの集まりです。
プログラミングではデータを受け取って、処理をして、どこかに送るという作業を繰り返すのですが、そのために用いられる箱の役割を果たします。
まず配列とは
同じ型のデータを複数個記憶する場所をメモリ上に連続して確保したもので、その確保した記憶場所に対して1つの名前をつけて、何番目の要素かを[添え字]で指示します。したがって、文字型配列とか、整数型配列という言い方をします。
そのため、以下のように宣言した配列をメモリ上で参照すると、
int a[5] = {1, 2, 3, 4, 5};
a[0] = 01 00 00 00
a[1] = 02 00 00 00
a[2] = 03 00 00 00
a[3] = 04 00 00 00
a[4] = 05 00 00 00
このような結果になり、これは「int型(4バイト)」のデータを5つ確保したよ、ということを表しています。
アドレスの基本的な考え
プログラム上の変数、定数などのデータはメモリ上に割り当てられています。つまり、どのようなデータも住所となるアドレスが自動的に割り振られており、そのアドレスは「&」演算子で参照することができます。
int a = 10; printf( "%016llx\n", &a);
このように変数宣言を行った場合、a は入れ物のことではなく、aという場所を確保した、という意味になります。
そして変数aの住所は『&a』で参照することができるため、Visual Studioなどのメモリウィンドウで『&a』とアドレス検索すれば、変数aの値を知ることができます。
配列のアドレス
「配列名」は配列の先頭アドレスを意味します。 そのため配列aから[添え字]を省略して a のように記述すると、a はそのデータ群の先頭アドレスを表すことになります。
また、C言語には「ポインタ」という概念があり、ポインタ宣言int *px;
を行うことによって「宣言したデータ型のアドレスを記憶できるポインタ」を作成することができます。
ポインタ変数はその値を参照することで、アドレス先にある値(変数の中身)を参照できます。
通常であれば、参照したい変数のアドレスを作成したポインタに代入することでポインタ変数として扱いますが、初めからアドレス自体に『﹡』を付けることでも、その変数のポインタとして利用することができます。
ポインタが値を参照する流れ
変数aに﹡が付いた『﹡a』は、変数aのポインタを表します。
ポインタには変数のアドレスが格納されているため、『﹡a』には変数aのアドレス(&a)が入っていることになります。
そのためポインタ(﹡a)に格納された値を辿ることで、変数aがどこにあるかという情報(&a)を知ることができ、結果的に変数aの値(a)を参照することができます。
また、配列名は配列の先頭アドレスを表す、ということから『﹡a』は配列aの最初の要素のアドレス、すなわち ﹡a = a[0] であることがわかります。
因みに以降の要素は、a[1] = ﹡(a+1)、a[2] = ﹡(a+2)、のようになります。
メモリウィンドウで『a』をアドレス検索することで、配列a[0]のメモリを確認できます。
また、以下のようなコードを書いた場合、
int a, *p; a = 10; p = &a;
『p』をアドレス検索で使用しても、配列a[0]のメモリを確認できます。
以上です。