如何为我的C结构体数组分配更多的空间?

8

我正在尝试向已经使用固定大小20进行了malloc的结构体中添加10个元素。这是我定义结构体的方式:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct st_temp {
   char *prod;
};

int main ()
{
   struct st_temp **temp_struct;

   size_t j;
   temp_struct = malloc (sizeof *temp_struct * 20);
   for (j = 0; j < 20; j++) {
      temp_struct[j] = malloc (sizeof *temp_struct[j]);
      temp_struct[j]->prod = "foo";
   }

   return 0;
}

我原本想通过realloc重新分配内存(不过,我不确定如何实现):

temp_struct = (struct st_temp **) realloc (st_temp, 10 * sizeof(struct st_temp*));

然后再添加额外的10个元素,

   for (j = 0; j < 10; j++)
      temp_struct[j]->prod = "some extra values";

我该如何实现这个?非常感谢您的帮助!

我同意Daniel的看法...为什么要使用双重指针间接性?如果这样做,不是更简单吗:struct st_temp * temp = malloc( 20 * sizeof *temp ); for (...) { temp[i].prod = "foo"; }?手动管理的内存越少,解决方案就越不易出错。 - David Rodríguez - dribeas
2个回答

9
当您使用 realloc() 时,必须提供新的大小,而不是要添加的字节数。因此:
temp_struct = (struct st_temp **) realloc (temp_struct, 30 * sizeof(struct st_temp*));

30当然是原始20加上10。如果realloc()函数需要移动内存块,它会负责将原始数据复制到新位置。

然后,添加额外的10个元素将类似于(从索引20开始,而不是0):

for (j = 20; j < 30; j++) {
    temp_struct[j]->prod = "some extra values"; 
}

有点太简单了,也许?将原始的误解加倍,认为不需要分配新对象(realloc并不这样做),而且没有错误处理(在C中相当关键)。 - eq-

7
为避免内存泄漏,我们需要小心处理重新分配(稍后会详细介绍)。realloc函数:

void *realloc(void *ptr, size_t size),其中

ptr = 原始(通过malloc分配的)内存块的指针,以及

size = 内存块的新大小(以字节为单位)。

realloc返回动态分配的内存块的新位置(可能已更改) - 或者如果重新分配失败,则返回NULL!如果返回NULL,则原始内存保持不变,因此您必须始终使用临时变量来存储realloc的返回值。

以下示例将有所说明(值得注意的是,realloc语法类似于malloc(无需额外转换等),并且在realloc之后,您需要为新对象执行与malloc相同的步骤):

struct st_temp **temp_struct;
temp_struct = malloc(20 * sizeof *temp_struct);
if (temp_struct == NULL) { /* handle failed malloc */ }
for (int i = 0; i < 20; ++i) {
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "foo";
}

// We need more space ... remember to use a temporary variable
struct st_temp **tmp;
tmp = realloc(temp_struct, 30 * sizeof *temp_struct);
if (tmp == NULL) { 
    // handle failed realloc, temp_struct is unchanged
} else {
    // everything went ok, update the original pointer (temp_struct)
    temp_struct = tmp; 
}
for (int i = 20; i < 30; ++i) { // notice the indexing, [20..30)
    // NOTICE: the realloc allocated more space for pointers
    // we still need to allocate space for each new object
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "bar";
}
// temp_struct now "holds" 30 temp_struct objects
// ...
// and always do remember, in the end
for (int i = 0; i < 30; ++i)
    free(temp_struct[i]);
free(temp_struct);

请注意,这不是一个结构体数组,而是一个指向结构体的指针数组——甚至可以是一个结构体数组的数组,如果您愿意的话。在最后一种情况下,每个子数组的长度将为1(因为我们只分配了一个结构体的空间)。

谢谢。非常有用的信息!你知道为什么我会得到“assignment from incompatible pointer type”错误吗?这是因为temp_struct = tmp;吗? - Josh
1
我在 tmp 的声明中打错了一个字母。 - eq-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接