プログラミング言語 C

C の 初心者は ときどき 2次元配列と、例として でてきた name のような ポインタ配列との 違いについて 混乱することがある。

下のような 定義が 与えられたとする:


  int a[10][20]; /* 2-dimensional array */

  int *b[10];    /* pointer array */

このとき、a[3][4] と b[3][4] とでは 両方とも 構文としては 規則に適った ある単一の int を 参照している。

しかし a は 本物の 2次元配列なので 200個の int サイズの location が 別に 確保されていて、a[row, col] の element を 求めると 20 x row + column という お約束の 直交的な 添字計算が 実行される。

b では、しかしながら、定義によって 10個の ポインタが 割り当てられるだけで、それら (← location) は 初期化されていない。

初期化は、static あるいは コードによって 明確に 行なわないといけない。

b の それぞれの element が (実際 すべての) 20個の element の 配列を 指すためには、200個の int プラス、ポインタ用の cell が 別に 確保されることになる。

ポインタ配列の 有利な点で 重要なのは、配列に 含まれる row が 異なった長さでも かまわないことである。 つまり、b の それぞれの element が (すべて) 20個の element を もつ ベクタを 指す必要はない。 (ある row では) 2つの element を 指し、あるものは 50個、また まったく 何も指さなくても かまわない。

ここまでの 議論では 整数 (integer) に 関してのみ 扱ったが、ポインタ配列が しばしば 用いられるのは、関数 month_name のように 異なった長さの 文字列を 格納するときである。(p138-139)

ポインタ配列の 宣言と ベクタとを、同じく 2次元配列の それと 比較してみよう:


char *name[] = {"Illigal month", "Jan", "Feb", "Mar"};

(vector)   name:
            . -----> Illigal month\0
            . -----> Jan\0
            . -----> Feb\0
            . -----> Mar\0


char aname[][15] = {"Illigal month", "Jan", "Feb", "Mar"};

  aname:
  Illigal month\0 Jan\0            Feb\0            Mar\0
  0              15               30               45