複雑な変数宣言をどう読むか?修飾子とポインタ

例:

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 のように、ある * の右側に近い場合は、その層のポインタを修飾する。

Leave a Reply