Cでは、非常によく似ているにもかかわらず、ポインターと配列は同じではありません。これは「 10intp
の配列へのポインタ」タイプです。これを「10intの4つの配列の配列へのポインタ」として使用しています。これは単一のメモリブロックです(唯一のポインタは最も外側のポインタです)。基本的には動的に割り当てられint[4][10]
ます。
これらの定義を読む秘訣は、アイテムを使用するのと同じ方法で記述されていることを理解することです。あなたが持っている場合:
*x[10];
配列の添え字が最初に適用され、次にポインターの逆参照が適用されます。したがって、を定義すると、ポインタの配列になりますint *x[10]
。括弧を使用して通常の優先順位をオーバーライドすると、ポインターの逆参照が最初に発生するため、配列へのポインターが得られます。
紛らわしい?ひどくなる。関数の引数では、関数パラメーターの最も外側の配列がポインターに変換されます。
int *p[10]; // array of 10 pointer to int
int (*p)[10]; // pointer to array of 10 ints
void foo(int *p[10] /* pointer to pointer to int */);
void foo(int (*p)[10] /* pointer to array of 10 ints */);
さらに、配列は、使用時にポインターに変換されます。
int x[10]; // array of 10 int
sizeof(x); // 10 * sizeof(int)
int *y = x; // implicitly converts to a pointer to &x[0]!
sizeof(y); // sizeof(int *)
これは、配列の配列にメモリを割り当て、それを暗黙的に配列へのポインタに変換できることを意味します。これにより、配列の配列であるかのように使用できます。
とにかく、これはすべて非常に紛らわしいので、本番コードでこれを使用しないでください-少なくとも、明確なtypedefなしではありません:
typedef int vector[3];
vector *array_of_vectors; // actually a pointer to a vector,
// but you can use it as an aray to a vector if enough
// memory is allocated