ポインタ配列
難しそうな題ですが、基本的にポインタと同じです。
一つ異なるのは、今までの考え方では配列の各要素(a[0],a[1],...,a[n])
それぞれのアドレスを入れる箱を作るのですが、ポインタ配列は一つの箱だけでよいのです。
コンピュータは配列を順番に並べて記憶しています。
つまり、配列の一番先頭の場所(アドレス)がわかれば、
それ以降の値は、“その場所(先頭アドレス)から何番目”というように処理することができるのです。
しかもポインタ配列は、配列と密接な関係にあるため、同じように扱うことができます。
<ポインタ配列>
#include<stdio.h>
main()
{
int i;
int a[5]={0,1,2,3,4}; /* このようにして初期化することもできます
*/
int *p;
p=&a[0]; /* 配列aの先頭アドレスをポインタpに入れている
*/
for(i=0;i<5;i++)
{
printf("%d\n",p[i]); /*
ポインタを配列みたいに扱っている */
}
} |
<実行結果>
上のプログラムで、例えば配列 a[] のアドレス(番地)が表左のようになっていたとすると、
それぞれポインタで表現するには、表右のようになります。
(int 型データは4バイトとします。2バイトの場合もあります。)
<配列とポインタの比較>
| 番地 |
データ |
|
配列で表現 |
ポインタで表現 |
ポインタの別の表現方法 |
| 100 |
0 |
|
a[0] |
*p |
p[0] |
| 104 |
1 |
|
a[1] |
*(p+1) |
p[1] |
| 108 |
2 |
|
a[2] |
*(p+2) |
p[2] |
| 112 |
3 |
|
a[3] |
*(p+3) |
p[3] |
| 116 |
4 |
|
a[4] |
*(p+4) |
p[4] |
アドレスが一度で4変わるのは、int 型データ1つを記憶するのに4バイト必要だからです。
上の表を参考にすると、プログラムは次のように書き換えることもできます。
<ポインタ配列その2>
#include<stdio.h>
main()
{
int i;
int a[5]={0,1,2,3,4}; /* このようにして初期化することもできます
*/
int *p;
p=&a[0]; /* 配列aの先頭アドレスをポインタpに入れている
*/
for(i=0;i<5;i++)
{
printf("%d\n",*(p+i)); /*
表のようにポインタで表現している */
}
} |
<ポインタ配列その3>
#include<stdio.h>
main()
{
int i;
int a[5]={0,1,2,3,4}; /* このようにして初期化することもできます
*/
int *p;
p=&a[0]; /* 配列aの先頭アドレスをポインタpに入れている
*/
for(i=0;i<5;i++)
{
printf("%d\n",*p); /*
ポインタで表現している */
p++; /*
アドレスを1つ分進めている */
}
} |
<ポインタ配列その4>
#include<stdio.h>
main()
{
int i;
int a[5]={0,1,2,3,4}; /* このようにして初期化することもできます
*/
int *p;
p=&a[0]; /* 配列aの先頭アドレスをポインタpに入れている
*/
for(i=0;i<5;i++)
{
printf("%d\n",p[i]); /*
ポインタで配列のように表現している */
}
} |
当然、実行結果は3つとも<ポインタ配列>のときと同じになります。
ここで、<ポインタ配列その3>のとき、配列を1ずらすたびにアドレスが4変わるなら、
なぜ p++ で大丈夫なんだ?
p++ は、p=p+1 という意味だから、
p が100番地を指しているなら、p++ で101番地を指すはずでは・・・
と疑問に思った方もいるでしょう。
これは、ポインタを宣言するときに、int *p; としたことで解決されます。
このように、“p は int 型データを扱うポインタである”と、最初から宣言することで、
コンピュータは間違えることなく、100番地の次の値を、
int 型データ1つ分をずらした104番地を指すようになるのです。
ちなみに、なんらかの配列を宣言したとき、その配列名はその配列自身の先頭アドレスを示します。
つまり、次のようなことが成り立ちます。
<例>
#include<stdio.h>
main()
{
int a[3]={0,1,2};
printf("&a[0]=%d\n",&a[0]); /*
配列の先頭アドレス */
printf("a=%d\n",a); /* これも配列の先頭アドレス */
} |
<実行結果>
<実行結果>の値は、パソコン,コンパイラにより異なりますが、2つとも値は同じになります。
このように、配列名の要素(a[3] の [3] の部分)をはずしたもの、つまり a は
その配列の先頭アドレスを示します。 |
|