配列とポインタ

配列名はその配列の先頭要素のアドレスを示す。

double a[] = {1, 2, 3, 4, 5};

cout << "a : " << a << endl;
cout << "&a[0] : " << &a[0] << endl;

出力結果は当然どちらも同じってことになる。
じゃあこれはどうなるのか。

cout << "&a : " << &a << endl;    // ?

結果はというと、自分の環境ではこれらすべて同値。

/* 出力結果
a : 0xbfd6b2f8
&a[0] : 0xbfd6b2f8
&a : 0xbfd6b2f8
*/

うーん。
なんかワケワカランと思ったので、次のようなコードも追加してみた。

cout << "(unsigned)sizeof(a) : " << (unsigned)sizeof(a) << endl;
cout << "(unsigned)sizeof(&a[0]) : " << (unsigned)sizeof(&a[0]) << endl;
cout << "(unsigned)sizeof(&a) : " << (unsigned)sizeof(&a) << endl;

cout << "=====================================" << endl;

cout << "*a :" << *a << endl;
cout << "*&a[0] : " << *&a[0] << endl;
cout << "*&a : " << *&a << endl;

cout << "=====================================" << endl;

cout << "(unsigned)sizeof(*a) : " << (unsigned)sizeof(*a) << endl;
cout << "(unsigned)sizeof(*&a[0]) : " << (unsigned)sizeof(*&a[0]) << endl;
cout << "(unsigned)sizeof(*&a) : " << (unsigned)sizeof(*&a) << endl;


結果はこんな感じに

/* 出力結果
(unsigned)sizeof(a) : 40
(unsigned)sizeof(&a[0]) : 4
(unsigned)sizeof(&a) : 4
=====================================
*a :1
*&a[0] : 1
*&a : 0xbfd6b2f8
=====================================
(unsigned)sizeof(*a) : 8
(unsigned)sizeof(*&a[0]) : 8
(unsigned)sizeof(*&a) : 40
*/

さらにワケがわからなくなってしまった...
結果を元に調べたら、最初の疑問も含め、頭の中を少しは整理できた気がするので以下にまとめる。

===
&a は配列全体のアドレスを表す。
(結果としては配列の先頭要素のアドレスが表示される。)

一方で、配列名 a と &a[0] は配列の先頭要素のアドレスを表す。

===
sizeof(*a) と sizeof(*&a[0]) は、配列の先頭要素を指すポインタを引数にとることになるので、格納された値の型のサイズがとれる(doubleなので8byte)。

一方で、sizeof(*&a) は配列全体を指すポインタを引数にとることになるので、配列全体のサイズ(8byte×要素数)がとれる。

===
sizeof(&a[0]) と sizeof(&a)ではアドレスのサイズ(4byte)がとれるが、配列名 a を引数にsizeofすると例外的に配列全体のサイズ(8byte×要素数)がとれる。


ただ、&a と*&a の出力が同じになることに、未だしっくりきていない感が...

今は自分の中でこうなるものと割り切っている部分もあるが、後々、より深い理解ができたら更新しようと思っているし、もし、これを見ている方がいたとして、ご指摘・ご教授くださるならすごく嬉しい。