C - 调用 malloc 后 p 如何成为二维数组?



以下代码片段使用malloc函数声明了一个 4 X 10的二维数组

/* 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之后会发生什么?我无法理解这一点。

在 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

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

也就是说,如果这段代码实际上是正确的。我的C在这一点上非常生疏。

首先,一些背景信息:

除非它是sizeof_Alignof或一元&运算符的操作数,或者是一个字符串文本用于初始化声明中的另一个数组,否则类型为 "T的 N 元素数组" 的表达式将转换为 "指针指向T" 的表达式,其值是数组中第一个元素的地址。 例如,给定数组

int a[10];

每当表达式a出现在代码中时,其类型将从"10 元素数组int"转换为"指向int的指针",或int *,除了像sizeof a_Alignof a&a这样的情况如果我们有一个 T 的 2D 数组,例如

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);我们在a后面找到类型为T的第i元素的地址并取消引用结果。 在这种情况下,p[i]为我们提供了p之后的第i10 元素int数组的地址。 由于我们在下标操作中取消引用指针,因此表达式p[i]的类型是"10 元素数组int"。 因此,我们可以再次下标此表达式并得到p[i][j]

相关内容

  • 没有找到相关文章

最新更新