【问题标题】:Using realloc to resize a dynamic array使用 realloc 调整动态数组的大小
【发布时间】:2015-05-29 14:22:57
【问题描述】:

我试图扩展我的完整玩家名单。

当我使用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");
    }
}

【问题讨论】:

    标签: c arrays memory-management malloc realloc


    【解决方案1】:

    更多类似:

    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..
    

    当然,只有当您的类型是指向指针列表的指针时。

    【讨论】:

      【解决方案2】:

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

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

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

      也就是说,

      • 请do not castmalloc()和C中的family返回值。
      • 请不要将realloc()的返回值直接存入目标指针。如果realloc() 失败,它将覆盖 valid 条目。

      【讨论】:

      • 所以你的意思是我需要做这样的事情: player[i] = realloc(player[i],sizeof(Player *)) ???
      • @user1703871 我已经更新了我的答案,你可以选择适合你的逻辑。 :-)
      • @user1703871 是的,如果你想改变player[i],你当然可以从initializeListForTree() 做。但是,你为什么要使用realloc()?一个简单的malloc() 有什么问题?
      【解决方案3】:

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

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

      最后一种情况发生的几率很大,所以你总是需要在拨打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;
          }
      

      基本上,先检查返回值,看是否成功:

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

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


      如果您的数组大小经常变化,那么您可能会分配更大的内存,记住它的大小,并仅在达到大小时重新分配它,当调整大小时,您也会给出比新值更大的值。

      调整大小时可以选择一个因子,例如factor = 1.5,表示:new_size = old_size * factor。

      【讨论】:

      • 好的,realloc 就是这样工作的,但你认为我需要做什么?
      • @user1703871 我更新了我的答案。只要您了解实际发生的情况,您就会知道该怎么做。
      猜你喜欢
      • 2017-08-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 2012-10-02
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多