Re:超テキトー図解ポインタ

id:mktx さんの「超テキトー図解ポインタ」、絵はかわいいですし面白い試みだと思うのですが、内容にちょっと問題があるように見えますので指摘しておきます。

冒頭で、ポインタをWindowsのショートカットや標識にたとえています。これについてブコメで批判もありますが、たとえ話は所詮たとえ話ですし、主観や感性の問題ですのでそこはよいかと思います。ショートカットでたとえるのはなかなかうまいと思いますし。

問題は、その後の「★気をつけること」です。

1.変数名に「*」をつけたものがポインタではない!

たとえば「int a;」としてint型の変数aを宣言し、これに*を付けて「*a」と書いてもポインタにはなりません。コンパイルエラーです。*ではなく&を付けて、「&a」と書けば、変数aへのポインタになります。
これは当たり前なので、おそらくここで言いたいことは、

int a;

という宣言に対し、

int *a;

と*を付けて書けばaへのポインタになる、という誤解(?)に対するカウンターとして

aに*つけても、自動的にaへのポインタにはならないよ。

と書いているんじゃないかなあ、と推測します。
もちろんその意味であれば、「aに*つけても、自動的にaへのポインタにはならないよ。」ということ自体は嘘ではないのかもしれませんが、Cにおいては、変数宣言と、その変数を実際に式の中で使うときとでは、同じ記号が全然違う意味を持つので、ここははっきり区別しておくべきでしょう。実際、宣言の中では、「int *a;」は「intへのポインタ」として変数aを宣言しますが、式の中で「*a」と書くときには、*はポインタをポインタでなくする方向に働きます。同じ記号なのになんだか意味が逆じゃないか? と思えないでしょうか。ここをごっちゃにするとわけがわからなくなります。宣言の中の*と式の中の*はまったく別物として考えるべきです

2.ポインタに代入するのは「アドレス」であり変数の値ではない。

ええと、

int a;
int *b;
int *c;

b = &a;
c = b;

と書いたとき、ポインタ型変数cに代入されているのはbという変数の値ですから、ポインタに変数の値が代入されてますが…というのは意地の悪い突っ込みですから置いといて、

ちがうよ! ポインタは箱じゃない。

変数を箱にたとえる*1のであれば、「ポインタ型の変数」はやはり箱です。

int a;
int *b;

b = &a;

と書いたとき、変数bという「箱」に、aのアドレスが格納された、と考えることができます。int型変数に「5」とかの値を格納するのと同じことです。

さてここで次のポイント。「ポインタ型」、「ポインタ型の値」、「ポインタ型の変数」は、それぞれ明確に区別してください。int型に、「intという型」、「int型の値(「5とか」)」、「int型の変数」があるように、ポインタにも、「(int*のような)ポインタ型」、「ポインタ型の値」、「ポインタ型の変数」があります。

int *a;

と書いたとき、これは、「intへのポインタ」という型の、変数aを宣言しています。
それをわかりやすくするために

int* a;

のように*をintのほうに寄せて書く人もいます。この書き方はいろいろ問題もあるのですが、意図するところはわかります。

int a;

のようにint型の変数aを宣言し、式の中で「&a」と書いたら、これは「intへのポインタという型の値」であり、具体的にはaのアドレスとなります。

というわけで、

3.宣言時の型は、「操作する変数の型」でポインタの型ではない。

ということはなく、

int *a;

という宣言における宣言時の型、すなわち「int*」は、まさしく「ポインタの型」です。
この場合のaは「int*」という型の変数であり、変数ですから、これに&を付けるとさらにaのアドレスを取得することができます。その場合の「&a」の型は「intへのポインタへのポインタ」となり、それを格納する変数を宣言したければ

int **b;

のように書くことになります。

このあたりについてより詳しく知りたいのなら、手前味噌ですがこちら。
http://kmaebashi.com/programmer/pointer.html

もっと詳しく知りたい方はぜひこちらを(宣伝)。

寝る前に一気に書いているのでまとまってなくてすみません。

*1:変数を「箱」にたとえることの是非については昔から散々議論されていることではあるのですが。