ポインタの混乱を防ぎたいメモ。

ポインタ変数とは

ポインタ変数は、普通の変数と同じく、何らかの文字に数値を格納しているものです。ただし、格納しているのがアドレスであるというのが、普通の変数とは異なる特徴です。

ここで、アドレスとは住所のことです。よく変数が箱に例えられますが、その箱には住所も割り当てられているということです。

& と *

アンパサンド(&)とアスタリスク(*)の意味を説明します。以下、普通の変数を a、ポインタ変数を p としています。

意味
&a a のアドレス
*p アドレス p に格納されている値

アドレスを見る 値を見る
&a a
p *p

& と * は、お互いに逆の意味を持ってる感じですね。

ポインタに変数のアドレスを代入するときは、
 p = &a;
と書きます。こうすることにより、*p == a になります。

宣言

変数を宣言するときは、
 int a;
のようにしますが、ポインタ変数を宣言するときは、
 int* p;
とします。ポインタの型は、アドレスを代入する変数の型に合わせます。型の後に * を付けることで、次の変数が普通の変数ではなくポインタ変数だということを示しています。

気を付けてほしいのは、この * が、先程述べた * とは違うものだということです。そのことを理解しておくと、ポインタの混乱が減らせると思います。

配列

配列 data[] があるとすると、配列の先頭アドレスは data と書くだけで表現できます。これは &data[0] と同じ意味になります。

まとめ

宣言 アドレスを見る 値を見る
int a; &a a
int* p; p *p
int data[10]; data data[0]

補足1:ポインタのサイズと型

ポインタ変数に格納される値は、他の変数の先頭1バイトのアドレスであり、アドレスのサイズは常に4バイトです(32ビット環境)。

ポインタの型は、ポインタ自身のサイズを決めるのではなく、ポインタが指す変数の型を表します。

ポインタの型の違いが顕著に見られるのは、アドレス演算のときです。char* 型のポインタ cp を cp++; すると cp の値が1増えますが、int* 型のポインタ ip を ip++; すると ip の値が4増えます。char のサイズが1バイト、int のサイズが4バイトだからです。

補足2:ポインタの宣言の書き方

ポインタの宣言は、
 int *p;
 int* p;
 int * p;
と、人によって書き方が異なります。昔の人は int *p; と書くことが多く、教科書でもよく見かけますが、この書き方は値を参照するときの *p と混同して入門者が混乱する原因になっているんじゃないかと思います。また、
 int *p = &a;
と書いたとき、実際に行われる代入は
 p = &a;
であるのに、*p に &a が代入されるように見えてしまうのもイマイチです。このことは、関数の引数にポインタを使うときにも同じことが言えます。

そんなような理由で、int* p; と書くほうが見た感じ分かりやすいのでオススメです。ただし欠点もあって、
 int* a, b;
と書いたとき、この意味は
 int* a;
 int b;
になってしまうので、その点にだけ気を付ける必要があります。

参考文献