C言語の基礎 |
a = 100;
は、コンピュータの内部では、次のように処理されている。
ユーザにとっては、"aという変数に100を代入する"と言うことであるが、コンピュータにとっては、"aという記号の指示するメモリ上のアドレスに100を格納する"ということをやっているわけである。このアドレスを扱うものをポインタといい、処理の高速化につながる。
3-1 ポインタ演算子
ポインタを扱うには、その変数に格納されているデータが、実際にメモリのどのアドレスに格納されているのかを知る必要がある。例えば、a = 100;
としたとき、この変数aが示しているアドレスが何番地であるかを知るために、アドレス演算子 &を使う。
pa = &a;
変数paには、変数aのアドレスが代入される。すなわち変数aのデータが実際に格納されているメモリのアドレスがわかったわけである。
次に、このアドレスの中に格納されているデータを知るために、ポインタ演算子 *を使う。
x = *pa;
変数xには、100が代入される。
次の例で確認してみよう。
/* sample16.c */ #include <stdio.h> int main(void) { int a, x; int *pa; /* ポインタ変数の宣言 */ a = 100; pa = &a; /* 変数aのアドレスを代入する */ printf("address=%x\n",pa); /* 変数aのアドレスを表示 */ x = *pa; /* 変数aのアドレスの内容をxに代入 */ printf("data:a=%d x=%d\n",a,x); }
address=XXXXXXXXXX |
& | 変数のアドレスを表す。 | &a, &b |
* | アドレスに格納されている内容を表す。 | *p, *a |
3-2 ポインタの宣言
ポインタを使用するには、ポインタ用の変数(変数のアドレスが格納される変数)が必要である。次のように宣言する。int *p;
char *pp; 今までの変数宣言と同じように宣言する。ただし、変数名の直前に*を付ける。(これからは普通の変数と区別するためにポインタ用の変数をポインタと呼ぶ。)
宣言しただけでは普通の変数と同じで、ポインタにはでたらめな内容が格納されている。したがって、どれかの変数のアドレスを代入しておかなければならない。これをポインタの初期化という。
変数aのアドレス | 変数aの内容 |
&a pa |
a *pa |
int a;
int *pa;
pa = &a; ← ポインタの初期化
3-3 ポインタと配列
ポインタは、配列とあわせて使用することで有効に利用することができる。/* sample17.c */
#include <stdio.h>
int main(void)
{
int a[4], i;
for(i = 0; i < 4; ++i)
a[i] = i * 10;
for(i = 0; i < 4; ++i)
printf("a[%d]=%d\n",i,a[i]);
}
a[0]=0 |
pa = &a[0];
とするとポインタpaに取り出せる。したがって、*paは変数a[0]と同じデータを表すことになる。
a[1]のデータを取り出したいときは、a[1]はa[0]の1つ次であるからa[0]を表すポインタ変数paに1を加えたら良いようである。
*(pa + 1)
ポインタpa(アドレスが格納されている)に1を加えてからポインタ演算子の*の処理をするように( )がつけてある。これでa[1]のデータがポインタを使って取り出せる。
このように配列のデータはすべてポインタで表現できる。
a[0] == *pa | a[2] == *(pa + 2) |
a[1] == *(pa + 1) | a[3] == *(pa + 3) |
上のプログラム(sample17.c)は次(sample18.c, sample19.c)のようにも書くことができる。
/* sample18.c */
#include <stdio.h>
int main(void)
{
int a[4], i;
int *pa;
pa = &a[0];
for(i = 0; i < 4; ++i)
*(pa + i) = i * 10;
for(i = 0; i < 4; ++i)
printf("a[%d]=%d\n",i,*(pa + i));
}
/* sample19.c */ #include <stdio.h> int main(void) { int a[4], i; int *pa; pa = &a[0]; for(i = 0; i < 4; ++i) *pa++ = i * 10; /* *(pa)にi*10の値を代入してからpaに1を加える */ pa = &a[0]; /* paの値が変化してしまったのでポインタを初期化 */ for(i = 0; i < 4; ++i) printf("a[%d]=%d\n",i,*pa++); }
*(pa+1)は、paが変数なので
pa = pa + 1;
と書くこともできる。同じようにpa=pa+1は、
++pa;
と書くこともできる。
ここで配列aとは何であろうか。次のsample20.cを実行してみよう。
/* sample20.c */
#include <stdio.h>
int main(void)
{
int a[4];
a[0] = 100;
printf("%d\n",a);
}
実行結果は、100が表示されずに訳のわからない数値が表示される。/* sample21.c */
#include <stdio.h>
int main(void)
{
int a[4];
a[0] = 100;
printf("%d\n",&a[0]);
printf("%d\n",a);
}
実行結果は、同じ数値が表示される。すなわち次のことが言える。
「配列名とは、配列の先頭のアドレスを示す定数である。」
したがって、
pa = &a[0];
は
pa = a;
と書くことができる。
最後に、ポインタというものについて見てみよう。
/* sample22.c */ #include <stdio.h> int main(void) { int a[4], i; int *pa; pa = a; for(i = 0; i < 4; ++i) *pa++ = 1000 + i; pa = a; for(i = 0; i < 4; ++i){ printf("a[%d]=%d pa=%d\n",i,*pa,pa); ++pa; /* pa = pa + 1 */ } }
a[0]=1000 pa=xxxxxx+0 |
Copyright © 2001-2003 Hiroshi Masuda |