C言語 : 配列とポインタ

配列へのポインタは面白い性質を持っている.

int foo[3] = {0};
int (*ptr)[3];

ptr = &foo;
printf ("ptr = %lu\n", (unsigned long)ptr);
printf ("foo = %lu\n", (unsigned long)foo);

これの実行結果は

ptr = 140737222446752
foo = 140737222446752


つまり,&foo と foo には値の違いはないというわけだ. ただ, 型は違うので同じとはみなせないということだ.
foo の型は int*
&foo の型は int[3]

配列と, ポインタは似ているが, はっきり区別されている.

また,

printf ("*ptr = %lu\n", (unsigned long)*ptr);
printf ("*foo = %lu\n", (unsigned long)*foo);

の実行結果は

*ptr = 140737222446752
*foo = 0

となる.
同じ値にもかかわらず,型によって結果が異なった.
定数を入れてみたかったけど, 取得は無理なので, 間接参照は必ず型チェックを通るということになる.

型によって, 同じ値でも演算は異なる. ポインタ関係では特にその傾向がある.

ptr は (int[3])* だから, 間接参照すると int[3] が返る. これはすなわち, そこにある配列の先頭アドレスなので, 値はそのままその地点のアドレスということだ. 値は同じだが, 配列の場所を示すアドレス -> 配列の先頭アドレス に変換されていることになる.
対して
foo は int* だから, 間接参照すると int が返り, これは foo の指すアドレスの値を指す(ややこしい)ということだ.
int の場所を示すアドレス -> int への変換が行われたのである.

今回はここまで.
次回はダブルポインタと二次元配列の違いについて書こうと思います.

Raptor