質問: a; printf("\n%d", p[2][1]); printf("\n%d", (p[2])[1]); return 0; }
回答: > > ・ポインタ変数は「参照先の型」と「アドレス」を保持している > > ・ポインタを1進めると「参照先の型」のサイズ分「アドレス」が増える > > ・ptr[i]は*(ptr+i)のシンタックスシュガーである > > ・ptr[i]はptrが指しているアドレスからi要素後ろの位置にあるアドレスに格納されているモノを示す > > > 上記はあなたの解釈で正しいです。 > > ・3次元の配列aにおいてa、a[0]、a[0][0]、&a[0][0][0]はいずれも評価すると配列の先頭アドレスを得られる > > > これは厳密には少々誤りを含んでいます。`int a[1][2][3]`のような3次元配列があるとき、それぞれの式の評価結果は **型(type)** が異なっています: * `a`は「3次元配列型`int[1][2][3]`の値」ですが、「2次元配列型`int[2][3]`を要素とする配列の先頭要素をさすポインタ値」へと変換され、評価結果は`int(*)[2][3]`型となります。 * `a[0]`は「2次元配列型`int[2][3]`の値」ですが、「1次元配列型`int[3]`を要素とする配列の先頭要素をさすポインタ値」へと変換され、評価結果は`int(*)[3]`型となります。 * `a[0][0]`は「配列型`int[3]`の値」ですが、「`int`型を要素とする配列の先頭要素をさすポインタ値」へと変換され、評価結果は`int*`型となります。 * `&a[0][0][0]`は「要素が`int`型配列の先頭要素をさすポインタ値」です。この式は`int*`型です。(最終結果は1つ上の`a[0][0]`と同じ) C言語のポインタと配列に関するルールのうち、「"配列型の値"は"配列の先頭要素をさすポインタ値"へと暗黙に変換される」というものがあります。(この分かりにくいルールのせいで、配列とポインタの混同がよく見られます) 簡単に型`T`の1次元配列`T a[N]`を考えたとき、式`a`自身の型は`T[N]`という「`N`個の`T`型要素からなる配列型」であり、この式の評価結果は「先頭要素`a[0]`をさすポインタ値」つまり ポインタ値`&a[0]`/`int*`型 へと暗黙変換されます。 また厳格な仕様解釈ではC言語に「多次元配列型」は存在せず、俗にいう3次元配列は「配列型の配列型の配列型」としてCコンパイラに解釈されています。上記のルールを再帰的に適用していけば、当初の疑問に答えられるかと思います。