WisdomSoft - for your serial experiences.

6.6 ポインタのポインタ

アドレスを保存するポインタも編集の一種であり、ポインタ自身もアドレスを持ちます。アドレス演算子を用いてポインタのアドレス、すなわちポインタへのポインタを取得できます。

6.6.1 ポインタのアドレス

ポインタの実体は参照先のアドレスを表す数値を保存するための一種の変数であると説明しました。ポインタもアドレスを保存する変数の一種であり、ポインタ自身のアドレスが存在します。言葉が再帰的になりますが、ポインタのポインタを作成することができるということです。つまり、ポインタのアドレスを別のポインタに格納することが可能なのです。

ポインタのポインタが参照しているのはポインタであり、このポインタからさらに参照している元の変数へアクセスすることもできます。このような多重間接参照の理解は、ポインタの概念において重要な部分ですのでしっかり押さえてください。ポインタのポインタを宣言するにはアスタリスク * をさらに付加します。

ポインタのポインタ宣言.
 **変数名;

多重間接参照を行うには、やはり間接演算子 * を参照を行うレベルの回数だけ指定します。ポインタの参照回数が多くなれば処理速度にも影響するため、無意味な多重間接参照は喜ばれるようなものではありません。しかし、開発者が保有しているポインタを他の関数から制御したい場合などにおいて、ポインタのポインタが利用されることがあります。

コード1
#include <stdio.h>

int main() {
	int iVariable = 100;
	int *ip = &iVariable;
	int **ipp = &ip;

	printf("--ip ポインタの示す値--\n");
	printf("アドレス = %p\n" , &ip);
	printf("保存するアドレス = %p\n" , ip);
	printf("保存するアドレスの内容 = %d\n\n" , *ip);

	printf("--ipp ポインタのポインタが示す値--\n");
	printf("保存する値 = %p\n" , ipp);
	printf("保存するアドレスの内容 = %p\n" , *ipp);
	printf("保存するアドレスのアドレスの内容 = %d\n", **ipp);

	return 0;
}
実行結果
コード1 実行結果

コード1は整数 100 を格納する変数 iVariable と、iVariable のアドレスを格納するポインタ ip、そして ip へのアドレスを格納するポインタのポインタ ipp が定義されています。このプログラムでは、ポインタと「ポインタのポインタ」の関係を理解するために、printf() 関数で各種の情報を表示します。表示されるアドレスは実行時によって異なりますが、上記の実行結果のようになるでしょう。

ポインタ ip のアドレスをアドレス演算子 & で取得することができます。ポインタのポインタ ipp はこれを保存しているため、ip のアドレスと ipp の保存する値は同一であることが確認できます。さらに ポインタのポインタ ipp を間接参照するということは、ip が保存する値を参照するということです。ipp が保存するアドレスの内容と、ip が保存するアドレスが同一であることから、これを確認することができます。

ポインタのポインタから、元の変数の値を参照するには、多重間接参照を行う必要があります。**ipp と記述することで多重間接参照を行い、最後の printf() 関数で、ipp が保存するアドレス(すなわち ip)が保存するアドレス(すなわち iVariable)を参照しています。