DOSEIの日記

技術メモ+日常ログ

Cでの2次元配列は、行列である。どういうことかというと、普通行といえば、連続したメモリ領域を想像する。array[][]はメモリアラインが[0][0], [0][1], ... [1][0], [1][1], ...となる。つまりarray[m][n]は、 n この連続データが m 個という意味になる。だから、arrayを行列に見立ててarray[i][j]をi,j 要素と呼ぶのがふさわしい。ま、0オリジンだけど。
2次元配列を座標と考えると、ちょっと困る。画像データは大抵x軸方向に連続である。通常の感覚ではimage[x][y]のように使いたくなる。しかし、実際はimage[y][x]のようにアクセスしないといけない。たとえば、画像データを一気にメモリにロードする場合、この順でないといけない。また、こうでないとx軸方向の連続アクセスに不利である。しかし、xとyが逆転しているので気分が悪い。だから、1次元で確保して、array[x + width * y]のように計算式を書く。せっかくの配列なのに。
Cの配列演算子(って言うんだっけ?)[]は2次元配列に対して1つだけ使うと、その行の先頭要素を指す。その性質上、配列の宣言時に最初の要素数(行数)は省略できても2番目の要素数(列数)は省略できない。なぜなら、array[M][N]と宣言された場合、array[m] == array + m * N + 1 であり、アドレッシングに必要だからである。同様にn次元配列でも、もっとも最初の要素数しか省略できない。
もっと自然な文法を導入したらどうか。[]はその前の型の配列とする。たとえば、array[4][5]は、(array[4])[5]、4要素の配列が5つの配列を作っているというような。これはつまり、array[x][y]で、xに対して連続なメモリ配置になる。この問題点は、たとえば2行目(y軸に2)の先頭を表わすポインタを取得するのに&array[0][2]とか書かないといけない。元の文法に比べて、ちょっと見づらい。