ポインタ
ポインタについて、第十章だけではまだまだわかりにくいので、
補足として今度はイメージ図を用いて説明したいと思います。
(最初からイメージ図を使っていれば良かったのですが、図を描くのは大変なので
今まで使ってませんでした。。)
次のプログラムを見てください。
<ポインタ>
#include<stdio.h>
main()
{
int a=10;
int *b;
b=&a;
printf("a=%d\n",a);
printf("&a=%d\n",&a);
printf("b=%d\n",b);
printf("&b=%d\n",&b);
printf("*b=%d\n",*b);
} |
順番にイメージ図で説明してゆきます。
まず、int a=10; で、パソコン内部に a という箱をつくり整数 10 を入れています。
次に、int *b; で、パソコン内部に b というアドレス専用の箱を作っています。
ここで、箱 a のあるアドレスが100番地だったと仮定します。
(このアドレスは勝手に決められるものです。
ここでは説明のため100番地だったと仮定します。)
すると、b=&a; で a のアドレスがアドレス専用の箱 b に入れられます。
(& がわからない人はこちら)

ここで、箱 b のあるアドレスが200番地だったと仮定します。
(もちろんこのアドレスも勝手に決められるものです。
ここでは、200番地だったと仮定します。)
つまり、現在の箱 a と、アドレス専用の箱 b の状態は次のようになっています。

見てのとおり、箱 a はアドレス100番地にあって、整数10を持っています。
アドレス専用の箱 b は、アドレス200番地にあって、箱 a のアドレスである100を
持っています。
この状態で、printf 関数によりそれぞれの値を画面に表示させることになります。
printf("a=%d\n",a);
a の箱にある値を表示するので、a=10 です。
printf("&a=%d\n",&a);
a の箱のあるアドレスを表示するので、&a=100 です。
printf("b=%d\n",b);
b の箱にある値を表示するので、b=100 です。
printf("&b=%d\n",&b);
b の箱のあるアドレスを表示するので、&b=200 です。
printf("*b=%d\n",*b);
b の箱にある値(つまり100)をアドレスとして、
そのアドレスにある箱(つまり a)の持つ値を
表示するので、*b=10 となります。
第十章 ポインタで*b についての説明が抜けていました。。(すいません。。)
また、言葉だけでは少しわかりにくいと思うので下の図を見てください。
ちなみに、第十章 ポインタでも述べましたが、
*b がポインタ変数ではなくて、b がポインタ変数です。
double 型のポインタである double * についても考え方は同じです。
(int * が double * になるだけです。)
また、一文字を扱うときの char * についても同じです。
しかし、文字列は次のポインタ配列と同じになります。 |
ポインタ配列
第十一章 ポインタ配列についてもイメージ図を用いて説明したいと思います。
次のプログラムを見てください。
<ポインタ配列>
#include<stdio.h> main() { int i;
int a[5]={10,11,12,13,14}; int
*p;
p=&a; for(i=0;i<5;i++) {
printf("%d %d %d\n",a[i],p[i],*(p+i)); } } |
<実行結果>
10 10 10
11 11 11
12 12 12
13 13 13
14 14 14 |
では、順番に見ていきましょう。
まず、int a[5]={10,11,12,13,14}; で
a という名前で、5個の int 型データの入る配列を作って、
10,11,12,13,14,15 の int 型データで初期化しています。

int *p; で、int 型データのアドレス専用の箱を作っています。

p=&a; で、アドレス専用の箱 p に、配列 a の先頭アドレスを入れています。
第十一章の最後にも述べたのですが、配列の名前、
つまり配列の [ ] をはずした a は、配列の先頭である a[0] を表します。
ここで、配列のアドレスは図のようなアドレスだったと仮定します。
4つ刻みになっているのは、int 型データが4つのアドレスを必要とするからです。
ちなみに、2つの場合もあります。(ここでは4つで考えます。)

さて、このように a[0] のアドレスだけを持つポインタ p を使って、
他の a[1] ,a[2] などの値を知るにはどうすればいいでしょうか?
答えは簡単です。
int 型の配列は、必ず4つ刻みのアドレスに入っています。
ということは、ポインタ p が持っているアドレスを4つ進ませた場所が
a[1] になります。
あとは、同じようにすべての配列の値を知ることができます。

しかし、p+4 としても a[1] のアドレスにはなりません。
実は、最初にポインタ変数を int *p; と宣言したときに、
コンピュータは、“p が持つアドレスは int 型データである”と知っているので、
わざわざ、“int 型データは4つ刻みだな”と考える必要はないのです。
ではどうすればいいのかと言うと、
a[1] のアドレスが知りたいならば、p+1 とすればいいのです。
つまり、int 型は4つとか考えず、
“a[0] の1つ後にある”という考え方でいいのです。
この考え方を図で表すと次のようになります。
p+1 〜 p+4 の箱が点線なのは、実際には作っていないからです。
配列のアドレスとポインタが持っている値を見比べてください。
それぞれ対応しているのがわかると思います。
ここで、注目してほしいのですが、
配列の [ ] の部分とポインタの足されている数を見比べてください。
例えば、[1] と +1 、[2] と +2 など、同じ数字になっています。
このことから、配列とポインタは密接な関係にあると言えるのです。
さらに、ポインタは配列のように書くこともできます。

このように、ポインタは配列と非常に密接な関係にあるのです。
文字列を扱うときに用いる char 型のポインタ char * は、
文字配列なので、こちらのポインタ配列と同じ考え方になります。 |
|