ポインタの配列
前のエントリのお題を再掲する。
以下の違いを説明せよ。 1)int a[2][3]; 2)int a[3][2]; 3)int *a[3]; 4)int (*a)[3]; 5)int **a;
次は3)のポインタの配列がどのようにメモリ上に配置されるかを見る。お題はint *a[3]であるが、扱いやすさと、実際のコードに現れやすいchar *a[3]を使ってサンプルコードを書く。C文字列はconst charの配列であるので、そこに特有の処理があるが、本質は同じである。
#include <stdio.h> #define ARRAY_NUM_OF(array) ((sizeof(array)) / (sizeof(array[0]))) int main(void) { char *a[3] = {"C", "C++", "Java"}; int i, j; printf("char *a[3] (array[3] Pointer to char)\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; a[i][j] != '\0'; j++) { printf("a[%d][%d] is @ %p\n", i, j, &a[i][j]); } } return 0; }
実行結果は以下のようになる。
$ ./main char *a[3] (array[3] Pointer to char) sizeof(a) = 12, sizeof(a[0]) = 4 a[0] is @ 0x22cd50 a[1] is @ 0x22cd54 a[2] is @ 0x22cd58 ====================== a[0][0] is @ 0x404000 a[1][0] is @ 0x404002 a[1][1] is @ 0x404003 a[1][2] is @ 0x404004 a[2][0] is @ 0x404006 a[2][1] is @ 0x404007 a[2][2] is @ 0x404008 a[2][3] is @ 0x404009
配列の配列の場合とは、メモリ上のアクセスの方法が、全く異なることがわかるだろう。
実行結果から、メモリマップを図に起こすと、以下のようになる。
[超重要ポイント]a[i][j]と言う記述だけでは、配列の配列なのかポインタの配列を[]演算子で参照しているのか不明