配列とアドレス演算子に関して

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
array

配列とアドレス演算子に関して

#1

投稿記事 by array » 10年前

配列名にアドレス演算子を作用させる操作は定義されているのでしょうか?

たとえば

コード:

  int a[2];
  int *p;
  p = (int *) malloc(2*sizeof(int));
  printf("a  : %p\n",  a);
  printf("&a : %p\n", &a);
  printf("p  : %p\n",  p);
  printf("&p : %p\n", &p);
を実行すると a と &a は同じ値になります。( p と &p は当然一般に異なる値になります。)

このコードにおいて、配列名 a は a[0] へのポインタになると思います。
しかしメモリ上に実体を持つポインタ変数 p とは違うのでアドレス演算子 & を作用させるのは未定義なのかなと思っていました。
しかし複数の環境で上のコードをためしたところどれも a = &a となります。

これは偶然でしょうか?
それともC言語では配列名にアドレス演算子を作用させる操作がこのように「配列名にアドレス演算子を作用させると、配列名と同じポインタ型の数値を返す」と定義されているのでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 配列とアドレス演算子に関して

#2

投稿記事 by h2so5 » 10年前

array さんが書きました:配列名にアドレス演算子を作用させる操作は定義されているのでしょうか?

たとえば

コード:

  int a[2];
  int *p;
  p = (int *) malloc(2*sizeof(int));
  printf("a  : %p\n",  a);
  printf("&a : %p\n", &a);
  printf("p  : %p\n",  p);
  printf("&p : %p\n", &p);
を実行すると a と &a は同じ値になります。( p と &p は当然一般に異なる値になります。)

このコードにおいて、配列名 a は a[0] へのポインタになると思います。
aはポインタではなくて配列です。その証拠に、sizeof(a)はsizeof(int*)と異なります。
ですから、&aはa[0]へのポインタへのポインタではなく、配列へのポインタ(= a[0]へのポインタ)です。
また、配列は先頭へのポインタにキャストすることができます。

つまり、

コード:

(void *)a == (void *)&a
となります。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 配列とアドレス演算子に関して

#3

投稿記事 by ISLe » 10年前

式の中に配列名が現れるとき、sizeof演算子のオペランド・アドレス演算子のオペランド・文字列リテラルのいずれかである場合を除き、配列の先頭要素を指すポインタに変換されます。
sizeof演算子のオペランド・アドレス演算子のオペランド・文字列リテラルのいずれかの場合は、配列全体を指します。

値が同じでも型が異なります。
aはintへのポインタ、&aはint[2]へのポインタ、です。

コード:

  int a[2];
  int *p;
  p = a; // &a[0]と同じ扱い
  p = &a; // エラー(Cでは警告) int (*)[2]からint *へ互換性のない変換 
(追記)
文字列リテラルに関して間違えました。
左辺値にできるかどうかとごっちゃにしてしまいました。

閉鎖

“C言語何でも質問掲示板” へ戻る