ポインタのポインタとは、あるポインタの値を別のポインタで指し示せるようにしたものです。
例えば、あるプログラミング言語では、整数型intのポインタのポインタを以下のように宣言できます。なお、ppは任意の名前です。
int **pp;
ポインタのポインタの初期化は、例えば、以下のように行います。
int a = 1;
int *p = &a;
int **pp;
pp = &p;
ポインタのポインタの宣言と初期化を同時に行う場合は、以下のようにします。
int a = 1;
int *p = &a;
int **pp = &p;
このとき、*ppでポインタpの値を指し示すことができます。**ppで*pを指し示すことができます。つまり、**ppと*pとaは同じメインメモリを参照します。
例えば、以下は、ポインタ配列をポインタのポインタで操作する例です。
int a[3] = {1, 2, 3};
int b[5] = {4, 5, 6, 7, 8};
int *p[2];
p[0] = a;
p[1] = b;
int **pp = p;
このとき、*ppでポインタp[0]の値を指し示すことができます。同様に、*(pp + 1)でポインタp[1]の値を指し示すことができます。
そして、ポインタのポインタppを使った配列aとbのそれぞれの要素の参照は、以下のように行えます。
配列aの1の要素:**pp
配列aの2の要素:*(*pp + 1)
配列bの4の要素:**(pp + 1)
配列bの6の要素:*(*(pp + 1) + 2)