指向结构的指针数组-为什么需要malloc(),为什么需要直接字段副本?

乌古

我想我对C中的内存和指针有一个基本的误解。我想问一个问题,为什么指向结构的指针数组需要malloc()调用该数组的各个元素,即使我想如果它们是分别初始化的,那么应该为他们自动分配内存。其次,在填充指针数组时,似乎有必要分别复制结构的元素,而仅将指针复制到结构本身是行不通的。

在其他程序中,我一直在使用结构和指针,而且我一直在寻找正确的方法来实现它们,因此我想直观地理解它,而不仅仅是想起“您只需要malloc()单个元素”这个词的阵列”

/* suppose I have "typedef struct coord { int x; int y; } coord;" */
int num_rooms = 5;
coord* coordinates[num_rooms];
int i, j;
/* why is this required? in the following loop, coord[i] gets initialized,
and I thought memory automatically gets allocated on the stack because of 
the initialization */
for (i = 0; i < num_rooms; i++) {
    coordinates[i] = (coord*) malloc(sizeof(coord));
}
/* fill the array of coord pointers */
for (j = 0; j < num_rooms; j++) {
    coord coordinate;
    coord *coord_p;
    coord_p = &coordinate;
    coord_p->x = j;
    coord_p->y = j;

    /* this does not work. It just makes all array elements have the same struct elements. (the second question) Why does it require copying over individual field elements instead of copying the pointer?*/
    //coordinates[j] = coord_p;

     /* however, assigning individual elements doesn't cause segmentation fault */
     coordinates[j]->x = coord_p->x;
     coordinates[j]->y = coord_p->y;
} 

如果我取消注释coordinates[i] = coord_p;,结果是数组的所有元素都有最后一个初始化的struct元素。因此,如果我打印每个坐标[i]-> x和坐标[i]-> y,它将说'4 4'5次。但是,当我使用直接struct元素副本时,如果我将其打印出来,则会得到正确的输出“ 0 0、1 1、2 2 ...”。

我希望不要为数组的各个元素分配内存,因为它们是在循环中初始化的。我也希望它coordinates[i] = coord_p;应该复制指针值,让类似的东西printf("%d", coordinates[0]->x);正常工作。但是,在两种情况下,我显然都误会了一些东西。

史蒂夫·萨米特(Steve Summit)

...为什么指向结构的指针数组需要为数组的各个元素调用malloc(),即使我认为如果要分别初始化它们,则应该为它们自动分配内存。

简单的答案是,从这个意义上讲C永远不会为您“自动”分配任何东西。

考虑它的一种方法是C为您的命名变量分配足够的内存,仅此而已。如果你说

int i;

C为一个分配足够的内存int如果你说

double a[10];

C分配足够的内存10double秒钟。如果你说

int *p;

C为一个指向int的指针分配了足够的内存,它没有为该指针指向分配任何内存!

几乎毫无例外,在声明指针时,您有责任考虑指针将指向的内存的分配。C永远不会自动为您做到这一点。

在您的特定示例中,当您说

coord* coordinates[5];

C为5个指针分配了空间coord-但为0个实际实例分配了空间coord另一方面,如果您说

coord coordinatesa[5];

C会为-的5个实际实例分配空间,coord尽管显然不使用此数组,因为不涉及指针。

当您分配了5个指针,但没有的实际实例时coord,如果您尝试使用其中一个指针,那将是一个严重的错误:

coord* coordinates[5];
coordinates[0]->x = 1;       /* WRONG */
coordinates[0]->y = 2;       /* WRONG */

解决此问题的一种方法是,首先确保coordinates[0]指向某处:

coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));
coordinates[0]->x = 1;       /* better */
coordinates[0]->y = 2;       /* better */

其次,在填充指针数组时,似乎有必要分别复制结构的元素,而仅将指针复制到结构本身是行不通的。

嗯,但是当您复制指针时,您将进行源指针的分配,而失去了目标指针的分配。

以我前面的示例为例,如果要说的话,请混入程序的一部分

coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));

coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coord_p->x = 1;
coord_p->y = 2;
coordinates[0] = coord_p;

这会“起作用”,但是很浪费,而且可能是错误的。malloc调用分配的内存永远不会使用,当您说

coordinates[0] = coord_p;

旧的指针将被覆盖,指向的内存(malloc恰好给您!)丢失了。

分配之后,由指向的内存分配就是分配的coordinates[0]任何内容coord_p,在这种情况下为单一coord结构coordinate正如我所说,这乍看起来似乎“可行”,但是如果coordinate局部变量超出范围,或者如果您最终将其重新用于coordinates数组中的所有5个坐标,则将会遇到问题。

另一方面,如果您说

*coordinates[0] = *coord_p;

或者,等效地,

coordinates[0]->x = coord_p->x;
coordinates[0]->y = coord_p->y;

现在,您将从coord指向的对象中获取数据coord_p,并将其安全地复制到指向的内存中coordinates[0]完成此操作后,您(a)正确使用了分配给您的内存coordinates[0]以指向,并且(b)使自己免受以后发生的任何事情所影响coord_p

但是,到目前为止,在这种情况下,我们根本不必使用中间coord_p指针。我们也可以说

coord coordinate;
coordinate.x = 1;
coordinate.y = 2;

*coordinates[0] = coordinate;

或者,等效地,

coordinates[0]->x = coordinate.x;
coordinates[0]->y = coordinate.y;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

是否需要创建指向结构的指针数组?

为什么要显式引用指向结构数组的指针而不是仅仅通过指针?

为什么指向结构的指针表现得像一个结构数组

为什么在rust中访问指向结构的指针上的字段?

指向函数中结构元素字段数组的指针

为什么在此堆栈实现中需要使用&传递指向结构的指针

为什么插入列表需要指向指针的指针

如何使用指向数组的指针访问结构数组中包含的结构中的字段?[C ++]

为什么指针需要类型?

为什么允许结构本身具有“指向其自身类型的指针”而不是成员“结构类型(的数组)”本身?

为什么需要$ el,它指向什么?

为什么在更改指向结构的指针后出现分段错误?

c-为什么指向结构的指针会使程序崩溃?

指向1D / 2D数组的指针的基本类型是什么,为什么需要双重解引用?

为什么我不能将指向固定大小数组的指针的地址传递给需要指向 C 中指针的指针的函数?

C-为什么指向指针的指针与指向数组的指针不一样?

在C中声明一个指向结构的指针的数组,但直到需要时才为结构分配内存

为什么在指针转换中需要(void *)?

为什么我需要双指针?

为什么需要指针类型转换?

为什么以及何时需要双指针?

为什么带有指针参数的成员函数需要指向指针的指针?

指向结构数组的指针

指向二维数组的指针(为什么起作用)

为什么我不能访问指向堆栈数组的指针?

为什么指向数组表达式的指针起作用

在 C 中使用指针时,我们何时以及为什么需要使用 malloc?

为什么结构需要朋友功能?

为什么需要在结构中填充?