1

以下代码段使用函数声明了一个4 X 10的二维数组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));

但我不明白怎么p变成二维数组。最初 p 被声明为指向 int 的指针数组。调用 malloc 后会发生什么?我无法理解这一点。

4

3 回答 3

3

内存,价值 40 个整数,保留给指针 p。p 指向他的内存块。碰巧 p 选择将这个记忆组织为 10 个相等的部分,每个部分恰好容纳 4 个整数的值。

那就是如果这段代码实际上是正确的。我的 C 在这一点上非常生锈。

于 2012-09-22T03:47:57.983 回答
3

在 C 中,尽管看起来非常相似,但指针和数组并不相同。这p是“指向 10 个整数数组的指针”类型。您将它用作“指向 4 个 10 个整数数组的数组的指针”,它是一个内存块(唯一的指针是最外层的指针)。它基本上是一个动态分配的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-element array of ”类型的表达式将被转换(“衰减”)为表达式类型为“指向”的指针,其值为数组中第一个元素的地址。例如,给定数组_Alignof&TT

int a[10];

每当表达式出现在代码中时a,其类型都会从“10 元素数组int”转换为“指针int”或int *除了、 和. 如果我们有一个 T 的二维数组,例如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]))。

那么这如何变成二维数组呢?

请记住,表达式a[i]等价于*(a + i); 我们找到后面类型的第i' 个元素的地址并取消引用结果。在这种情况下,为我们提供了以下10 元素数组的地址。由于我们取消引用指针作为下标操作的一部分,因此表达式的类型是“10 元素数组”。因此我们可以再次下标这个表达式并得到。 Tap[i]iintpp[i]intp[i][j]

于 2012-09-22T14:28:34.330 回答