【问题标题】:How do I allocate more space for my array of C structs?如何为我的 C 结构数组分配更多空间?
【发布时间】:2011-05-03 04:31:16
【问题描述】:

我正在尝试向我的结构添加 10 个以上的元素,这些元素已经是 malloc 且固定大小为 20。这就是我定义结构的方式:

#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;
}

所以我的想法是重新分配为(但是,不确定如何):

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"; } 不是更简单吗?您手动管理的内存越少,解决方案就越不容易出错。

标签: c struct malloc realloc


【解决方案1】:

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

void *realloc(void *ptr, size_t size),在哪里

ptr = 指向原始(malloc'ed)内存块的指针,以及

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(因为我们只为一个结构分配空间)。

【讨论】:

  • 谢谢。很棒的信息!,你知道我为什么会得到:temp_struct = tmp 时指针类型不兼容的赋值; ?
  • 我在tmp 的声明中有错字。
【解决方案2】:

当您使用realloc() 时,您必须给出new 大小而不是要添加的字节数。所以:

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 中有些关键)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 2015-06-13
  • 1970-01-01
  • 2012-06-08
  • 2020-12-20
  • 2021-12-05
相关资源
最近更新 更多