配列要素を参照するシンタックスバリエーション

C言語では、以下のシンタックスは、すべて'B'に展開される。
(文字列リテラル"ABCDE"の格納領域の先頭アドレスを、0x8048560と仮定します。)

# syntax
1 "ABCDE"[1]
2 ((char *)0x8048560)[1]
3 1["ABCDE"]
4 (&"ABCDE")[0][1]
5 0[(&"ABCDE")][1]
  1. 式中の文字列リテラルは、配列シンボルと同様の扱いを受ける。つまり、配列の先頭要素へのポインタに展開される。array[i]は、*(array+i)に展開されることも同様。ただし、間接演算子*や添字で間接参照しても、左辺値にはなり得ない。
  1. アドレスを即値指定もできるが、参照先のデータ型(サイズ)が不明であるとアドレス計算ができないので、(char *)とキャストする必要がある(参照先がchar型であると伝える)。
  1. array[i]は*(array+i)に展開されるということは、i[array]は、*(i+array)に展開される。交換法則により、両者は同じ意味となる。
  1. アドレス演算子をつけることで、配列"ABCDE"へのポインタ('A'へのポインタではないことに注意)に展開される。(&"ABCDE")[0]は、*(&"ABCDE"+0) → *(&"ABCDE")と展開され、間接演算子*とアドレス演算子が打ち消しあうので、結局、"ABCDE"と同じである。これに[1]をつけると、No1と同じシンタックスとなる。
  1. No4の(&"ABCDE")と0を入れ替えただけなので、交換法則により、No4と同じ意味となる。

トリッキーなコードの主眼は、見た目の珍奇さよりも、「原理を理解しているか」であると思う。