array、&array[0]、&arrayの違い
添字指定の無い配列名を参照すると、「配列の先頭要素へのポインタ」として参照されますが、&演算子がついた配列名とは、どう違うのでしょうか。
[array.c]
1 #include <stdio.h> 2 3 int main(void) 4 { 5 int array[5]; 6 7 printf("%p -> %p\n", array, array+1); 8 printf("%p -> %p\n", &array[0], &array[0]+1); 9 printf("%p -> %p\n", &array, &array+1); 10 11 return 0; 12 }
[出力結果]
$ ./array 0xbf901b1c -> 0xbf901b20 # 4バイト差 0xbf901b1c -> 0xbf901b20 # 4バイト差 0xbf901b1c -> 0xbf901b30 # 20バイト差
array、&array[0]、&arrayとも、展開されるアドレスは一致しています。しかし、1インクリメントした先のアドレスは、それぞれ、4バイト先、4バイト先、20バイト先を示しています。
T型のポインタに対して+nした場合、(n * sizeof(T))バイト数分アドレスが進むため、それぞれの要素サイズ(sizeof(T))は、
array # (要素サイズ = 4バイト)のオブジェクト &array[0] # (要素サイズ = 4バイト)のオブジェクト &array # (要素サイズ = 20バイト)のオブジェクト
と解釈されていることになります。
つまり、arrayと&arrayは、展開されるポインタ値は一致しているものの、
array … 配列の0番目の要素(array[0])へのポインタ &array … 配列全体(int array[])へのポインタ
という意味で解釈されていることが分かります。
まとめ。
「配列の先頭要素へのポインタ」と、「配列全体へのポインタ」は、同じアドレスを指していたとしても、配列要素の単位サイズは異なる。