違いを理解するには、2つの異なるコンテキストを理解する必要があります。
- 値のコンテキストでは、型の配列の名前は型へ
T
のポインターとT
同等であり、配列の最初の要素へのポインターと同じです。
- オブジェクトコンテキストでは、型の配列の名前はポインタ
T
になりません。
オブジェクトコンテキストとは何ですか?
でa = b;
、a
はオブジェクトコンテキストにあります。変数のアドレスを取得すると、オブジェクトコンテキストで使用されます。最後にsizeof
、変数で演算子を使用すると、オブジェクトコンテキストで使用されます。他のすべての場合、変数は値のコンテキストで使用されます。
これで、この知識が得られました。
void f(int arr[4]);
とまったく同じです
void f(int *arr);
ご存知のように、関数宣言からサイズ(上記の4)を省略できます。これは、に渡される「配列」のサイズがわからないことを意味しますf()
。後で、あなたがするとき:
int a[]={1,2,3,4};
f(a);
関数呼び出しでは、名前a
は値コンテキストにあるため、へのポインターになりint
ます。f
へのポインタを期待しているので、これは良いことですint
。したがって、関数の定義と使用は一致します。渡されるのは、 ( )f()
の最初の要素へのポインタです。a
&a[0]
の場合
int a[]={1,2,3,4};
int b[4] = a;
名前b
はオブジェクトコンテキストで使用され、ポインタに還元されません。(ちなみに、a
ここは値のコンテキストにあり、ポインターになります。)
ここで、int b[4];
4秒のストレージに相当するストレージを割り当てint
、それに名前b
を付けます。 a
同様のストレージも割り当てられました。したがって、実際には、上記の割り当ては「保管場所を以前の場所と同じにしたい」という意味です。これは意味がありません。
の内容をにコピーする場合は、次のようにすることができます。a
b
#include <string.h>
int b[4];
memcpy(b, a, sizeof b);
または、以下を指すポインタb
が必要な場合a
:
int *b = a;
ここで、a
は値のコンテキストにあり、へのポインタに還元されるためint
、に割り当てることができa
ますint *
。
最後に、配列を初期化するときに、明示的な値を割り当てることができます。
int a[] = {1, 2, 3, 4};
ここで、aには1、2、3、および4に初期化された4つの要素があります。次のこともできます。
int a[4] = {1, 2, 3, 4};
リスト内の要素が配列内の要素数よりも少ない場合、残りの値は0と見なされます。
int a[4] = {1, 2};
a[2]
とa[3]
を0に設定します。