プログラミング言語 C

ポインタは 他の変数のアドレスを 内容とする 変数であり、C では 頻繁に 使用される。その一つの理由は、それが 時に 計算を表現する 唯一の方法である場合であり、もう一つの理由は、他の方法で 得られるより 通常、もっとコンパクトで 効率のよいプログラムが 書けるからである。

ポインタは、理解できないようなプログラムを つくってしまう要因として、goto 文と 並び称されてきた。不用意に使うと、確かに これは事実であって、(まちがって) 予想もしない場所を 指し示す ポインタを つくるのは 簡単である。

しかし 十分に注意すれば、ポインタを用いて 明快で シンプルな プログラムを つくることができる。

ポインタの宣言、
int *p;
は、表記法として 設けられたもので *p という表現が int であることを 表す (ポインタが 指す先の値 - オブジェクト - が int 型である、という意味)。

このことは 関数の宣言でも あてはまる。例えば、
double *p, atof(char *);
では、*p と atof() とは double の型を もっており、atof() の引数が char 型 (の オブジェクト) への ポインタであることを 表現している。

単項演算子 & は オブジェクトのアドレスを 与えるから、
p = &c;
では、変数 p に c のアドレスが 代入される。このとき p は c を "指し示す" という。& 演算子は メモリ中の オブジェクト、すなわち 変数 および 配列要素にのみ 適用できる。& 演算子を 式や 定数、レジスタ変数に 適用することは できない。

次に、単項演算子 * は、間接演算子 すなわち 逆参照演算子である。これを ポインタに適用すると、そのポインタが指す オブジェクトが アクセスできる。

int x;
p = &x;
p は x を指す -> p に x のアドレスが 代入される。

*p = 1
p の指す オブジェクトに '1' が 代入される。

y = *p
p の指す オブジェクトが y に代入される。

p が (int 型で) 整数 x を指すとすると、*p は x が使われる コンテクストでは どこでも 使うことができる。

*p = *p + 10
では、*p (p の指す オブジェクト) を 10 増やしている。

単項演算子 & と * は、算術演算子よりも 束縛力が 強い。そのため、
y = *p + 1;
では、p の指す オブジェクトが 何であれ、それが 取り出され '1' が 加えられて、その結果が y に 代入される。

(*p)++;
も 同様である。ただし、この場合には カッコが 必要となる。(なぜなら) * や ++ のような 単項演算子では、右から左へと 計算されるため、カッコがないと p の指す オブジェクトではなく、p そのものを インクリメントしてしまう。


最後に、ポインタは 変数であるので 逆参照なしに (* 演算子を 用いずに) 使うことができる。例えば、
int *p, int *q;
int x = 1;
p = &x;
q = p;
とすると、 p そのものが q へ代入され (結果として) q は p の指す オブジェクトを 指すこととなる (この場合は '1')。(p113-116)