char two_array[2][3] = { "ab", "cd" }; のとき
私が理解している範囲で two_array[0][0] を読むと、
からE1[E2]が (*((E1)+(E2)))と等価であると定義する。
[C99 6.5.2.1 から一部引用]
となり、簡素化するとtwo_array[0][0] → (*((two_array)+(0)))[0] → (*((*((two_array)+(0)))+(0)))
と読む。(*(*(two_array)))
(*(*(two_array))) を演算子の優先順位に従い
と読んでいました。two_array → *two_arrayへのポインタ
* → *two_arrayへのポインタを間接参照 = **two_arryaへのポインタ
* → **two_arrayへのポインタを間接参照 = 'a'
しかし規格には、
と定義してあり、左辺値が3つの例外(sizeof演算子のオペランド、単項&演算子のオペランド、文字列配列を初期化するのに使われる文字列リテラル)を除く [〜型の配列] をもつ式は、[〜型へのポインタ] の式に型変換する。
それは配列オブジェクトの先頭の要素を指し、左辺値ではない。
[C99 6.3.2.1 から一部引用]
は、間違いでありtwo_array → *two_arrayへのポインタ
となる。two_array → 配列オブジェクトの先頭の要素へのポインタ
そうすると、 char array[5] = "abcd"; で1次元配列の array[0] なら
array[0] → (*(array)) を演算子の優先順位に従い
と規格通りに読むことが出来るのですが、2次元配列の two_array[0][0] を[C99 6.3.2.1]の通りに読むと、array → 配列オブジェクトの先頭の要素へのポインタ
* → 配列オブジェクトの先頭の要素へのポインタを間接参照 = 先頭の要素( = 'a')
two_array[0][0] → (*(*(two_array))) を演算子の優先順位に従い
と2個目の間接参照を無視した形になってしまうと思います。two_array → 配列オブジェクトの先頭の要素へのポインタ
* → 配列オブジェクトの先頭の要素へのポインタを間接参照 = 先頭要素( = 'a')
* → 先頭要素( = 'a')を間接参照??(先頭要素( = 'a')の型はポインタじゃないので[C99 6.5.3.2 アドレス及び間接演算子]の定義により間接参照できない。)
two_array が指しているメモリを調べて(%p ← two_array)、先頭要素(two_array[0][0] = (*(*(two_array))) )を指しているのは確認しました。
ただ (*(*(two_array))) を読むときに、
と読んでしまうと、 ** の2重間接参照の説明がつきません。two_array → 配列オブジェクトの先頭の要素へのポインタ
なぜ [ two_array → *two_array へのポインタ ] と読んだかというと、ポインタ演算の定義の、
から、ポインタに1加算すると、そのポインタが指す型のサイズ増加する。(この解釈が違う??)ポインタ型の式[P]が配列オブジェクトの第i要素を指すなら、[(P)+N]は、「Pのアドレス+n×オブジェクトの大きさ」のアドレスを指す。
[C99 6.5.6 並びに 新ANSI C言語辞典 p284 加算演算子 から一部引用]
two_array+1 は、アドレスが3増加 (3増加する型はchar[3])
型がchar[3]のポインタは *two_array である。(typeid(*two_array).name() → A3_c)
つまり、ポインタ(two_array)が指すのは *two_array であるから 3増加する。
と考えて読みました。
two_array が配列の先頭要素(two_array[0][0] = (*(*(two_array))) )を指しているポインタだとすると、
(*(*(two_array))) の型はcharなので (typeid(**two_array).name() → c) 1増加になるはずです。
以上のポインタ演算の定義から考えると、two_array は、 *two_array を指していると読むことができてしまいます。
例えば [C99 6.3.2.1] に定義されている他に、
のような定義が、どこかに定義してあるなら全てが納得出来ますが、見つけることが出来ませんでした。配列名が、配列の先頭要素へのポインタを指すのはある限定的な場合に限る
厳密な読み方がわからなくても *two_array、**two_array、が式の中でどうゆう結果になるのかはわかりますが、その課程を規格に沿った形で読む方法が知りたいです。
ご教示お願い致します。