二次元配列の受け渡し

二次元配列

C言語の二次元配列は、一次元配列をさらに配列にしたもの と考えられる。例として二次元配列 x[3][4] を考えよう。 この配列の初期要素を以下のようにする。

  int x[3][4] = {
    1, 2, 3, 4,		/* x[0][*] の4要素 */
    10, 20, 30, 40,	/* x[1][*] の4要素 */
    100, 200, 300, 400	/* x[2][*] の4要素 */
  };

上記の宣言によって、以下のような値が入る。

x[R][C]x[*][0] x[*][1]x[*][2] x[*][3]
x[0][*]1233
x[1][*]10203040
x[2][*]100200300400

これをまとめて別の関数に受け渡す場合、もらう側の仮引数では かならず第2添字のサイズを指定しなければ正しく受け取ることができない。 つまり、以下のようにする。

/* もらう側の関数定義 */
float sub(int array[][4], int n)
{
  .......
}

/* 呼出側の記述 */
int main()
{
  int x[3][4] = {
    1, 2, 3, 4,		/* x[0][*] の4要素 */
    10, 20, 30, 40,	/* x[1][*] の4要素 */
    100, 200, 300, 400	/* x[2][*] の4要素 */
  };
  float result;
  avg = sub(x, 5);
}

二次元配列のしくみ

コンピュータのメモリは、1バイトをしまう場所に一つ一つアドレス(番地)が ついている。アドレスは数字一つの通し番号なので、これは1次元である。

000000010002……0200……



……
……

もし、x[3][4] のような配列があっても、それが実際に

x[R][C]x[*][0] x[*][1]x[*][2] x[*][3]
x[0][*]1233
x[1][*]10203040
x[2][*]100200300400

のような2次元平面の上にに配置されるわけではなく、各要素が順番に配置さ れる。もし、0x1000番地(16進数)から順番に配列要素を保存するとしたら、

  1. x[0][0]
  2. x[0][1]
  3. x[0][2]
  4. x[0][3]
  5. x[1][0]
  6. x[1][1]
  7. x[1][2]
  8. x[1][3]
  9. x[2][0]
    :
    :

という風に格納される。コンピュータは、配列の添字から実際の 格納アドレスを知るために、2次元配列の添字を使ってアドレスを計算する。

x[R][C] のアドレス = 1000番地 + R×4 + C

このようなアドレスを求めるためには、第2添字の最大個数が 分からなければ計算できない。この理由により、関数で配列を受け取るときには

/* もらう側の関数定義 */
float sub(int array[][4], int n)
{
  .......
}

のように第2添字の大きさを指定しなければならないのである。

1次元配列といい2次元配列といいサイズをいちいち指定しないと いけなくてめんどいな… とくに2次元配列なんか配列を大きくすると 仮引数の書き方も変えなきゃいけないからプログラムの修正が 繁雑そうだ… うーむ、これでいいのか?
続く.....


目次