使用 realloc 调整动态数组的大小

Using realloc to resize a dynamic array

我试图扩展我的完整玩家列表。

当我使用realloc函数时,它保存了我的播放器,除了最后一个。 我的意思是,如果我的数组中有 4 个玩家,并且我尝试将数组扩展到 7 个,我会得到一个大小为 7 且只有 3 个玩家的新数组。

这是函数的一部分:

void initializeListForTree(Player** players, int listSize)
{
    int formulaSize = bla bla bla.....
    players = (Player **)realloc(players, sizeof(Player *)*formulaSize);
    if (!players)
    {
        printf("memory allocation failed\n");
    }
}

不,您不能从 initializeListForTree() 函数更改 players 本身 ()。 C 使用按值传递函数参数传递。在 initializeListForTree() 函数中对 player 所做的任何更改都不会 反映 到实际使用的参数。

如果您必须完成此操作,则需要将指针传递给 players

如果您不介意有其他方法,如果选择 return 新的 从 initializeListForTree() 分配指针并将其收集到传递的实际参数中,那么您将不需要传递 pointer-to-pointer-to-pointer.

也就是说,

  • do not castmalloc()和家人C的return值。
  • 请不要将 realloc() 的 return 值直接 存储到目标指针中。如果 realloc() 失败,它将覆盖 valid 条目。

更多类似内容:

void initializeListForTree(Player*** players, int listSize)
{
int formulaSize = bla bla bla.....
void *p = realloc(*players, sizeof(Player *)*formulaSize);

  if (!p) {
      printf("memory allocation failed\n");
  }
  else {
    *players = p;
  }
}

并在调用站点

Player **playerslist = NULL;   

initializeListForTree(&playerslist, 1);
 ...
initializeListForTree(&playerslist, 2);
 etc..

当然,前提是您的类型是指向指针列表的指针。

在哪里 realloc() 找到扩展内存:

  • 如果原来的内存后有足够的空闲space,那么它会使用那个,并且原来的地址不会改变。
  • 如果原始内存在堆/.. 的末尾,它会扩展内存,因此原始地址不会改变。
  • 如果原来的内存在heap/..的中间,而没有足够的space,那么它会分配一个新的内存块,并将你原来的内存复制到新的内存中,所以地址改变。

最后一种情况发生的几率很大,所以你总是需要在调用后更新你的地址realloc()

而且旧地址可能会被放入空闲内存列表中,你不应该再碰它了。它可能会在未来由另一个 malloc()/.. 调用分配。

而且你可以看到,realloc()可能很重,因为它可能需要复制内存,所以改进代码,尽可能避免使用它。


这是一个可能的用例(来自 TLPI):

    // nptr is new pointer, ptr is your original pointer,

    nptr = realloc(ptr, newsize);
    if (nptr == NULL) {
        /* Handle error */
    } else {
        /* realloc() succeeded */
        ptr = nptr;
    }

基本上先检查return值看是否成功:

  • 如果失败,则原内存不变。
  • 如果成功,将新地址分配给原始指针。

而且,你需要确保你没有另一个指向原始内存中间的指针,因为它也会改变,使用偏移量作为起始地址可以使事情变得更容易。


如果你的数组大小经常变化,那么你可能会分配一个更大的内存,记住它的大小,只有在达到大小时才重新分配它,当调整大小时你也给一个比新值更大的值。

您可以在调整大小时选择一个系数,例如factor = 1.5,表示:new_size = old_size * factor