使用 realloc 调整动态数组的大小
Using realloc to resize a dynamic array
我试图扩展我的完整玩家列表。
当我使用reallo
c函数时,它保存了我的播放器,除了最后一个。
我的意思是,如果我的数组中有 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 cast
malloc()
和家人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
。
我试图扩展我的完整玩家列表。
当我使用reallo
c函数时,它保存了我的播放器,除了最后一个。
我的意思是,如果我的数组中有 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 cast
malloc()
和家人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
。