めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

「配列へのポインタ」と「ポインタの配列」の見分け方

はい。どちらでしょう。

int (*hoge)[10]

答えは、配列へのポインタなのですが、(私を含めて・・・)どうしても、ポインタの配列に見えて仕方がない人は、次の手順で構文解析してください。

まず、丸カッコでポインタ記号(*)がhogeに縛り付けられているので、「ポインタ」が最後の述語になります。

「hoge は (punyo) へのポインタ」ーーー (1)

その上で、(*hoge) → punyoと置き換えます。

int punyo[10]

これはすぐに分かります。

「punyo は int の10要素の配列」ーーー (2)

最後に(2)を(1)に代入します。

「hoge は、int の10要素の配列へのポインタ」

すっきり!

ちなみに・・・

hoge の両側にある * と [10] はどちらの方が強く hoge に結びつくのでしょうか? 一般に、識別子(hoge)の右側のものがより強く結びつきます。したがって、先の丸カッコをとりのぞくと・・・

int *hoge[10]

[10]の方が hoge に結びついて、今度は、「配列」が最後の術後になります。

「hogeは、(puni)の10要素の配列」ーーー (3)

先と同様に、hoge[10] → puni と置き換えると、

int *puni

これから、

「puni は、int へのポインタ」ーーー (4)

となるので、(4)を(3)に代入すると、

「hogeは、int へのポインタの10要素の配列」

すっきり!

このあたりは、「エキスパートCプログラミング」という書籍で詳しく解説されています。

――――――――――――――

ニッチな話題に☆をいただいたのに気をよくして追記です。

前述の書籍「エキスパートCプログラミング」にも出ている例題です。

char *(*c[10])(int **p)

cの正体は何でしょう?

先に識別子の右のものが強く結びつくと言いましたが、正確には、右・左・右・左・・・と交互に結びついていきます。この例では、次のように4つの要素が結びつきます。

   4   2   1      3
   |   |   |      |
------ - ---- ---------
char *(*c[10])(int **p)

そして、ここが間違いやすい(直感と合いにくい)所ですが、先に結びついたものがより後ろの述語になりますので、答えはこんな感じです。

cは・・・

1.                                           10要素のリスト
2.                                   へのポインタの
3.             intへのポインタへのポインタpを受け取る関数
4. charへのポインタを返す

英語脳ならこんな風に自然に解釈できるのかな・・・

c is a list with 10 elements, which contains a pointer, which points to a function receiving (int **p), which returns a pointer to char.

とも思いますが、上記の書籍の著者(オリジナルは英語)もぶつぶつ言っているので、そうでもないのかも知れません。