1

次のスニペットは、関数を使用して4X10の2次元配列を宣言しますmalloc

/* Declare a pointer to an array that has 10
ints in each row. */
int (*p)[10];
register int i, j;
/* allocate memory to hold a 4 x 10 array */
p = malloc(40*sizeof(int));

But I do not understand how does p become a 2-D array. Initially p is declared to be an array of pointers that point to int. What happens after the call to malloc ? I am unable understand this.

4

3 に答える 3

3

40 intに相当するメモリは、ポインタpに予約されています。pは彼のメモリブロックを指しています。たまたま、pはこのメモリを10個の等しい部分として編成することを選択し、それぞれがたまたま4intの価値を保持します。

これは、このコードが実際に正しい場合です。私のCはこの時点で非常に錆びています。

于 2012-09-22T03:47:57.983 に答える
3

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
于 2012-09-22T03:55:09.870 に答える
0

まず、いくつかの背景情報:

、、、または単項演算子のオペランドである場合、または宣言内の別の配列を初期化するために使用される文字列リテラルである場合を除き、sizeof「N要素配列」型の式は式に変換(「減衰」)されますタイプは「pointerto 」であり、その値は配列の最初の要素のアドレスです。たとえば、配列が与えられた場合_Alignof&TT

int a[10];

aがコードに現れると、その型は「の10要素配列int」から「ポインタint」、または、、、、などの場合int *除いて変換されます。Tの2D配列がある場合、sizeof a_Alignof a&a

int a[10][10];

aは、タイプ「10要素配列の10要素配列int」から「ポインターから10要素配列のint」に変換されます。またはint (*)[10](見覚えがありますか?それがポインターのタイプですp)。

タイプのN要素配列を動的に割り当てたい場合は、次のTように記述します。

T *p = malloc(N * sizeof *p);

sizeof *pと同等sizeof (T)です。この特定のケースでは、タイプTは「の10要素配列int」またはint [10]です。このような配列を4つ割り当てたいので、次のように記述できます。

int (*p)[10];
p = malloc(4 * sizeof *p);

これにより、の4つの10要素配列にスペースが割り当てられint、結果がに割り当てられpます。(sizeof *p == sizeof (int [10]))。

では、これはどのようにして2D配列になりますか?

式は;a[i]と同等であることに注意してください。次のタイプの'番目の要素*(a + i)のアドレスを見つけ、結果を逆参照します。この場合、次の10要素配列のアドレスがわかります。添え字演算の一部としてポインタを逆参照するため、式の型「10要素の配列」です。したがって、この式に再度添え字を付けて、を取得できます。 iTap[i]iintpp[i]intp[i][j]

于 2012-09-22T14:28:34.330 に答える