【配列とポインタ】第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;    /* ○正しいコード例 */

式中における*<配列へのポインタ>が返す値のデータ型はポインタですが、配列のデータ型は、あくまで配列というデータ型(正確には派生型)です。