问动态分配数组后(如问题 6.14 所述),我可以更改其大小吗?
答可以。这正是realloc的作用。给定一段malloc分配的内存(例如问题 6.14 中的dynarray),可以使用以下代码更改其大小:
dynarray = realloc(dynarray, 20 * sizeof(int));请注意,realloc[脚注]可能并不总是在原地扩展内存区域。如果可以,它只是返回您传递给它的相同指针;但如果它必须转移到内存的其他部分才能找到足够的连续空间,它将返回一个不同的指针(并且之前的指针值将变得不可用)。
如果realloc找不到足够的空间,它会返回一个空指针,并保持先前的区域已分配。[脚注] 因此,通常您不想立即将新指针分配给旧变量。而是使用一个临时指针。
#include <stdio.h> #include <stdlib.h> int *newarray = (int *)realloc((void *)dynarray, 20 * sizeof(int)); if(newarray != NULL) dynarray = newarray; else { fprintf(stderr, "Can't reallocate memory\n"); /* dynarray remains allocated */ }
重新分配内存时,如果存在指向该内存的任何其他指针(即“别名”),请务必小心:如果realloc必须将新区域定位在其他位置,则还必须调整这些其他指针。这是一个例子(人为的,并且不小心使用malloc的返回值)
#include <stdio.h> #include <stdlib.h> #include <string.h> char *p, *p2, *newp; int tmpoffset; p = malloc(10); strcpy(p, "Hello,"); /* p is a string */ p2 = strchr(p, ','); /* p2 points into that string */ tmpoffset = p2 - p; newp = realloc(p, 20); if(newp != NULL) { p = newp; /* p may have moved */ p2 = p + tmpoffset; /* relocate p2 as well */ strcpy(p2, ", world!"); } printf("%s\n", p);(最安全的方法是根据偏移量重新计算指针,如上面的代码片段所示。另一种方法是根据差异重新定位指针,newp - p,即realloc调用之前和之后基指针的值之差,但不能保证这种方法有效,因为指针减法仅定义为对指向同一对象的指针执行时才有效。另请参见问题 7.21。)
参考:《K&R2》第 B5 节,第 252 页
ISO 第 7.10.3.4 节
《H&S》第 16.3 节,第 387-8 页