第十一章 ポインタ配列


ポインタ配列                                                             
難しそうな題ですが、基本的にポインタと同じです。

一つ異なるのは、今までの考え方では配列の各要素(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]);     /* ポインタを配列みたいに扱っている */
    }
}
<実行結果>
0
1
2
3
4

上のプログラムで、例えば配列 a[] のアドレス(番地)が表左のようになっていたとすると、
それぞれポインタで表現するには、表右のようになります。
(int 型データは4バイトとします。2バイトの場合もあります。)

<配列とポインタの比較>
番地 データ 配列で表現 ポインタで表現 ポインタの別の表現方法
100 a[0] *p p[0]
104 a[1] *(p+1) p[1]
108 a[2] *(p+2) p[2]
112 a[3] *(p+3) p[3]
116 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);       /* これも配列の先頭アドレス */
}
<実行結果>
&a[0]=1245044
a=1245044

<実行結果>
の値は、パソコン,コンパイラにより異なりますが、2つとも値は同じになります。
このように、配列名の要素(a[3] の [3] の部分)をはずしたもの、つまり a は
その配列の先頭アドレスを示します。

<前に戻る  |目次|  次へ進む>