配列とポインタ
配列名はその配列の先頭要素のアドレスを示す。
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 の出力が同じになることに、未だしっくりきていない感が...
今は自分の中でこうなるものと割り切っている部分もあるが、後々、より深い理解ができたら更新しようと思っているし、もし、これを見ている方がいたとして、ご指摘・ご教授くださるならすごく嬉しい。