配列の配列
C言語で配列とポインタの理解は第一関門だと思う。私が、C言語のスキルを試すときによくやる質問は次のような物だ。
以下の違いを説明せよ。 1)int a[2][3]; 2)int a[3][2]; 3)int *a[3]; 4)int (*a)[3]; 5)int **a;
普通にCを書ける人でも、これに満足に答えられる人は余りいない。上から目線の言い方になるが、これがちゃんと説明できる人は自信を持ってイイと思う。
C言語に多次元配列は無い
int a[N][M]; a[i][j] = 2;
こんな書き方ができるのだから、「論理的には多次元配列が扱える」という立場もあるが、それだと上記1)〜5)の違いを理解するのに邪魔になる。C言語で扱える配列はあくまでも1次元であり、配列の配列という形式で多次元配列のように見せている、というのが実際である。
#include <stdio.h> #define ARRAY_NUM_OF(array) ((sizeof(array)) / (sizeof(array[0]))) int main(void) { int a[2][3]; int i, j; printf("int a[2][3] (array[2] of array[3] of int\n"); printf("sizeof(a) = %u, sizeof(a[0]) = %u\n", sizeof(a), sizeof(a[0])); for (i = 0; i < ARRAY_NUM_OF(a); i++) { printf(" a[%d] is @ %p\n", i, &a[i]); } printf("====================== \n"); for (i = 0; i < ARRAY_NUM_OF(a); i++) { for (j = 0; j < ARRAY_NUM_OF(a[i]); j++) { printf("a[%d][%d] is @ %p\n", i, j, &a[i][j]); } } return 0; }
実行結果
$ ./main int a[2][3] (array[2] of array[3] of int sizeof(a) = 24, sizeof(a[0]) = 12 a[0] is @ 0x22cd40 a[1] is @ 0x22cd4c ====================== a[0][0] is @ 0x22cd40 a[0][1] is @ 0x22cd44 a[0][2] is @ 0x22cd48 a[1][0] is @ 0x22cd4c a[1][1] is @ 0x22cd50 a[1][2] is @ 0x22cd54
上記の結果からメモリマップを書いてみると、以下のようにメモリ上に並んでいることがわかる。
決して2×3というようなイメージではなく、一直線上にint[3]が2つ並んでいるのである。
これがわかれば1)と2)の違いは自ずとわかる。2)はint[2]が3つ並んでいる。