多次元配列

  多次元配列を利用することも可能です.例えば,2 次元及び 3 次元の配列に対しては以下のように宣言します.
int a[3][2];   // 2 次元配列
double b[3][2][5];   // 3 次元配列		
  このように宣言することによって,例えば,2 次元配列の場合,int 型のデータが 3 * 2 = 6 個入る連続した領域が確保され.a[0][0],a[0][1],a[1][0],a[1][1],a[2][0],a[2][1] の順に記憶されます.つまり,最も右側の添え字から順に変化していきます.この点は 3 次元配列においても同様です.

  配列に対し連続的な領域が確保されていますので,2 次元の配列を 1 次元の配列として処理することも可能です( 3 次元以上でも可能).例えば,
int *z = (int *)a;   // z = &a[0][0]; でも良い		
のような処理をすれば,z[3] と a[1][1] が同じ場所を指すことになります.一般に,a[i][j] と z[(i×k) + j] は,同じ場所を指すことになります.ただし,k は,配列変数 a の宣言における列の数です(上の例では 2 ).さらに,
int *z = &a[1][0]; // int *z = a[1]; でも良い		
のような処理をすれば,配列 a の 2 行目以降を 1 次元配列として扱うことができます.

  また,初期化も,例えば,以下のような方法で可能です.最も左側の添え字に対応する要素数は省略できますが,それ以外は省略できません.誤りと書いたものを除き,各宣言とも正しく初期設定されると共に,各行の右側に書かれたような領域が確保されます.
int x1[][] = {{1, 2}, {3, 4}, {5, 6}};     // 誤り
int x1[3][2] = {{1, 2}, {3, 4}, {5, 6}};   // 3行2列  int x1[3][2] {{1, 2}, {3, 4}, {5, 6}}; も OK
int x2[][2] = {{1, 2}, {3, 4}};   // 2行2列  int x2[][2] {{1, 2}, {3, 4}}; も OK
int x3[3][] = {{1, 2}, {3, 4}};            // 誤り
char c1[5][10] = {"zero", "one", "two", "three"};   // 5行10列
char c2[][10] = {"zero", "one", "two", "three"};    // 4行10列
char *c3[] = {"zero", "one", "two", "three"};       // 4つのポインタ
char c4[5][] = {"zero", "one", "two", "three"};     // 誤り		
  new 演算子を使用して,2 次元以上の配列も確保できます.例えば,2 行 3 列(行や列の数は変数でも構わない)の配列を確保するためには,以下のように記述します.この結果,概念的には,右図に示すような領域が確保されます.ただし,必ずしも連続した領域になるとは限りません.
double** pd = new double* [2];   // 2つの要素からなるポインタの配列
for (i1 = 0; i1 < 2; i1++)
	pd[i1] = new double [3];   // 行毎に列数を変えることも可能
		// 以下のような方法で初期設定も可能
double** pd = new double* [2];
pd[0] = new double [3] {1, 2, 3};
pd[1] = new double [3] {4, 5, 6};		
また,解放するときは,以下のようになります.開放する順番に注意して下さい.
for (i1 = 0; i1 < 2; i1++)
	delete [] pd[i1];
delete [] pd;