【配列とポインタ】第2回 配列へのポインタ
式中において、ポインタに間接演算子*をつけると、参照先の値に展開される…というのは当たり前ですが、
int型変数へのポインタに*をつけると、int型の値に展開される。
char型変数へのポインタに*をつけると、char型の値に展開される。
ポインタ型変数へのポインタに*をつけると、ポインタ型の値に展開される。
では、「配列型変数へのポインタに*をつけると、何に展開される」?
流れでいくと、「配列に展開される」と言えそうですが、実験してみます。
1 char arr[] = "0123456789"; 2 char (*ptr_to_arr)[] = &arr;
コード例のように、T型配列を指すポインタ変数は、以下のように宣言します。
1 <T> (*<変数名>)[]
ptr_to_arrは配列arrを指すポインタ変数ですが、これに*をつけた*ptr_to_arrは、以下のように参照先文字列arrの先頭要素へのポインタに展開されます。
1 printf("location (symbol) value \n"); 2 printf("--------------------------- ----------\n"); 3 printf("%p (ptr_to_arr) : %p %s\n", 4 &ptr_to_arr, ptr_to_arr, *prt_to_arr); 5 printf("%p (arr) : %s\n", &arr, arr);
# 実行結果 location (symbol) value *ptr_to_arr --------------------------- ---------- ----------- 0xbfece208 (ptr_to_arr) 0xbfece221 0123456789 0xbfece221 (arr) 0123456789
0xbfece221 (arr) +---------------------------------------------------------------+ | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | +---------------------------------------------------------------+ ***** ↑ *ptr_to_arr *************************************************************** ↑ +------------+ | 0xbfece221 | +------------+ 0xbfece208 (ptr_to_arr)
以上より、
配列αへのポインタに*をつけて間接参照すると、(配列αに展開されるわけではなく)配列αの先頭要素へのポインタに展開される。
と言えそうです。
もう一度、おさらいすると、
int型変数を指すポインタに*をつけると、int型変数の値に展開される。 char型変数を指すポインタに*をつけると、char型変数の値に展開される。 ポインタ型変数を指すポインタに*をつけると、ポインタ型変数の値に展開される。 そして、配列αを指すポインタに*をつけると、αの先頭要素へのポインタに展開される。
なお、「*<配列αへのポインタ>が、配列αの先頭要素へのポインタに展開される」からといって、配列の実体がポインタである、というわけではないです。
例えば、配列へのポインタを、ポインタへのポインタに代入することはできません。例えば、以下のコード例をコンパイルすると、シンタックスエラーが発生します。
1 char arr[] = "0123456789"; 2 char **ptr_to_ptr = &arr; /* ×間違ったコード例 */
# コンパイルエラー 警告: 互換性のないポインタ型からの初期化です [デフォルトで有効]
正しくは、以下のように「配列へのポインタ」にしか代入できません。
1 char arr[] = "0123456789"; 2 char (*ptr_to_arr)[] = &arr; /* ○正しいコード例 */
式中における*<配列へのポインタ>が返す値のデータ型はポインタですが、配列のデータ型は、あくまで配列というデータ型(正確には派生型)です。