例:
const char **p;
char *const *p;
char **const p;
C 言語の複雑な変数宣言を読むときは、まず変数名を見つけ、その周囲の記号を「近いものから遠いものへ、右から左へ」の順に読んでいくとよい。括弧がある場合は、括弧内を優先する。ポインタと const について重要なのは、const が何を修飾しているかを判断することだ。const が の左側にある場合は、通常は指されているデータを修飾する。 の右側にある場合は、そのポインタ自体を修飾する。
まず次を見る:
const char **p;
p はポインタである。その指す先の内容もまたポインタであり、2 段目のポインタが最終的に指しているのは const char である。つまり、p は「ポインタへのポインタ」であり、最も内側の文字データはこの型を通じて変更できない。次のように読める:p はポインタで、別のポインタを指し、その別のポインタは定数文字を指している。
次に見る:
char *const *p;
変数名 p から読み始めると、p はまず左側の最も近い と結び付くので、p はポインタである。このポインタが指している内容は char const、つまり「定数ポインタ」である。この定数ポインタ自体は別の場所を指すように変更できないが、それが指している char の内容は const ではないため、それを通じて変更できる。
したがって、char const p は次のように読める:p はポインタで、定数ポインタを指し、その定数ポインタは char を指している。
最後に見る:
char **const p;
ここでは const が最も外側の の右側にあるため、修飾しているのは変数 p というポインタ自体である。つまり、p は定数ポインタであり、別のアドレスを指すようには変更できない。p が指している内容は char であり、その char * がさらに char を指している。
次のように読める:p は定数ポインタで、char * ポインタを指し、そのポインタは char を指している。
まとめると次のようになる:
const char **p; // p はポインタへのポインタで、最も内側のデータは const char
char *const *p; // p は const ポインタへのポインタで、その const ポインタは char を指す
char **const p; // p 自体が const ポインタで、char * を指す
実用的な判断方法は、変数名から外側へ読んでいき、 を見るたびに「ポインタ」の層を 1 つ加えることだ。const を見たら、それがどの層に近いかを見る。const char のように const が型名に近い場合はデータを修飾する。const のように、ある * の右側に近い場合は、その層のポインタを修飾する。
