覚えておくべき重要な点は、C と C++ の両方で、多次元配列は単に配列の配列であるということです (つまり、3 次元配列は配列の配列の配列です)。多次元配列のすべての構文とセマンティクスは、(もちろん、言語の他の規則からも) それに従っています。
したがって、オブジェクト定義が与えられた場合:
int m[2][2][2];
m
型のオブジェクトですint[2][2][2]
(それぞれが 2 つの要素で構成され、それぞれが 2 つの要素で構成され、それぞれが 2 つの配列である 2 つint
の配列の配列)。
あなたが書くときm[1][1][1]
、あなたはすでに評価していますm
、m[1]
そしてm[1][1]
。
式m
は、 type の配列オブジェクトを参照する左辺値int[2][2][2]
です。
ではm[1]
、配列式m
は配列の最初の要素へのポインタに暗黙的に変換 (「減衰」) されます。このポインタの型は でint(*)[2][2]
、 の 2 要素配列の 2 要素配列へのポインタですint
。m[1]
定義上、 と同等*(m+1)
です。は1 要素分+1
進みm
、結果のポインター値を逆参照します。Som[1]
型のオブジェクト(それぞれが 2 つの要素int[2][2]
で構成される 2 つの配列の配列) を参照します。int
(配列のインデックス演算子は、配列ではなくポインター[]
を操作するように定義されています。 のような一般的なケースでは、ポインターはたまたま配列からポインターへの暗黙的な変換の結果です。)arr[42]
に対してプロセスを繰り返し、(タイプ の) m[1][1]
2 つの の配列へのポインタを与えます。int
int(*)[2]
最後に、m[1][1][1]
評価の結果を受け取り、m[1][1]
プロセスをもう一度繰り返して、 type のオブジェクトを参照する左辺値を提供しますint
。これが多次元配列の仕組みです。
軽薄さに加えて、式のような式はfoo[index1][index2][index3]
、配列だけでなくポインターでも直接機能します。つまり、ポインターと任意のサイズの割り当てを使用して、(ほぼ) 真の多次元配列のように機能するものを構築できるということです。これにより、行ごとに異なる数の要素を持つ「不規則な」配列、または行と要素が欠落している可能性さえあります。ただし、各行または各要素の割り当てと割り当て解除を管理するのはあなた次第です。
推奨される読み物: comp.lang.c FAQのセクション 6 。
補足: 多次元配列が配列の配列ではない言語があります。たとえば、(配列のインデックス付けに角括弧ではなく括弧を使用する) Ada では、 のようにインデックス付けされた配列の配列を使用したり、 のようarr(i)(j)
にインデックス付けされた 2 次元配列を使用したりできますarr(i, j)
。C は異なります。C には、多次元配列に対する直接の組み込みサポートはありませんが、それらを自分で作成するためのツールが提供されます。