はじめての C

基本に 戻って、K&R 2nd を 再チェック、
http://www4.kcn.ne.jp/~yoitiro/hatena/knr2nd_6.txt

2次元配列を 関数に 渡す場合は、列の数 number of columns が なければならない。 渡されるのは 行 row の 配列のポインタだから、行の数 number of rows は 無関係である。

func(int daytab[][13]) { .... }

あるいは

func(int (*daytab)[13]) { .... }

と 書ける。 これは 13個の 配列のポインタで あることを 示している。(p136-137)

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

int a[10][20]; /* 2次元配列 */

int *b[10]; /* ポインタ配列 */

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

しかし a は 本物の 2次元配列なので 200個の int サイズの 場所 location が 別に 確保されていて、a[row][column] の 要素 element を 求めると、

20 x row + column

という お約束の 直交的な 添字計算が 実行される。

b では、しかしながら 10個の ポインタが 割り当てられるだけで、それら - location - は 初期化されていない。

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

b の それぞれの element が 20個の 要素を 指すためには、200個の int プラス、ポインタ用の cell が 別に 確保されることになる。

ポインタ配列の 有利な点で 重要なのは、配列に 含まれる 行 row が 異なった 長さでも かまわないことである。

つまり、b の それぞれの element が 20個の element をもつ vector を (すべて) 指す 必要がない。

(ある 行 row では) 2つの element を 指し、あるものは 50個、また まったく 何も 指さなくても かまわない。(p138)

これが、「index (補助の ポインタ配列) を 実行時 runtime に 割り当てる」ための 理由か ...
2次元配列を ダブルポインタに 渡す 場合では、

#include <stdio.h>
#include <stdlib.h>

int func();

main()
{
short mat[3][4], i, j;

for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
mat[i][j] = i * 10 + j;

func(mat);
}

int func(short **mat)
{
short i, j, *index[4];

for (i = 0; i < 3; i++)
index[i] = (short *)mat + 4 * i;

for (i = 0; i < 3; i++) {
printf("\n");
for (j = 0; j < 4; j++)
printf("%5.2d", index[i][j]);
}
printf("\n");

return;
}