違いを理解するには、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同様のストレージも割り当てられました。したがって、実際には、上記の割り当ては「保管場所を以前の場所と同じにしたい」という意味です。これは意味がありません。
の内容をにコピーする場合は、次のようにすることができます。ab
#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に設定します。