配列とポインタの関係

今回と配列とポインタです。
まずは、配列とポインタのおさらいをしておきましょう。

配列
変数の型 配列名[ 要素数 ];

ポインタ
型* 変数名

配列とポインタは、一見全く関係なさそうですが、実は大きな関係があります。
例を見てみましょう。

スポンサーリンク

サンプルプログラム

ソースファイル名:main.c

実行方法

上のソースを書き写して実行してください。
配列 array の値と、ptr の値に注目してください。

配列の先頭アドレス

配列とポインタは大きな関係があります。
サンプルプログラムで、array は

char array[ 4 ] = { 10, 5, 3, 2 };

と定義されていて、char 型の変数を4つ持つ配列になっています。
また、ptr は、

char *ptr;

と定義され、char 型の変数のアドレスを格納する事ができます。
今回のポイントは、

printf( "array = %d¥n", array );

です。
配列を扱う時は、array[ 0 ]のように[]で要素の番号を指定する必要があると言いました。
しかし、今回は、[] がありません。

このように配列に[]を付けずに表記するときは、その配列の先頭アドレスを表します。
先頭アドレスとは、要素 0 番のアドレスのことです。

【 図1 】

配列イメージ

図1で、配列 array[ 4 ] が 2002 番地から 4 バイト割り当てられているとすると、2002 番地が先頭アドレスになります。
これは、

&array[ 0 ]

と書いても同じことになります。

先頭アドレスとポインタ

array は配列の先頭アドレスを表します。
アドレスという事は、ポインタに代入することができるということです。
それが、サンプルプログラムの

ptr = array;

の部分です。これは、

ptr = &array[ 0 ];

とイコールです。
ptr には配列 array の先頭アドレスが代入されます。
図1で言うと、2002 番地です。

ポインタは、メモリを間接的に参照する時に使用すると以前お伝えしました。
配列でももちろん同じことができます。
つまり、ptr に入ったアドレスから array の要素を参照することができるのです。

ポインタを使って配列の間接参照

サンプルプログラムでポインタ ptr を使って、array の値を参照している部分が

for( i = 0; i < 4; i ++ )
{
  printf( "ptr[ %d ] = %d¥n", i, ptr[ i ] );
}

になります。
ptr は array の先頭アドレスを持っているので、array と同じく配列として扱うことができます。
つまり、[]を使って、その要素を得る事ができるのです。

サンプルプログラムを実行すると、ptr[ i ] で参照した値と、array[ i ] で参照した値が同じになることが確認できます。

配列のメモリ上の配置

配列とポインタの関係を知った上で、配列のメモリ上での配置を説明します。
改めて図1を見てみます。

配列イメージ

配列は、メモリ上に順番に配置されます。
図1で言うと、仮に array[ 0 ] が 2002 番地に置かれているとしたら、

array[ 1 ] = 2003 番地
array[ 2 ] = 2004 番地
array[ 3 ] = 2005 番地

というように、順番に配置されます。
サンプルプログラムでは、

ptr = array;

として、ptr には array の先頭アドレスが入っています。 ptr が配列の先頭アドレスを持っているのなら、アドレスを進めながら値を参照することも可能なはずです。

for( i = 0; i < 4; i ++ )
{
  printf( "ptr[ i ] = %d¥n", *ptr );
  ptr ++; }

このようにすれば、ptr のアドレスを 1 づつ進めながらその値を参照できます。
アドレスを進めながら値を参照するので、最初は 2002 番地、次に 2003 番地というように、配列の中身を順番にとっていくことができるのです。
これは、

for( i = 0; i < 4; i ++ )
{
  printf( "ptr[ i ] = %d¥n", ptr[ i ] );
}

と同じ結果を得ることになります。

スポンサーリンク