我们可能需要时不时地增加或减少为指针分配的内存,如果需要一个变长数组这种做法尤其有用,数组会讨论这一点。realloc
函数会重新分配内存,下面是它的原型:
void *realloc(void *ptr, size_t size);
realloc
函数返回指向内存块的指针。该函数接受两个参数,第一个参数是指向原内存块的指针,第二个是请求的大小。重新分配的块大小和第一个参数引用的块大小不同。返回值是指向重新分配的内存的指针。
请求的大小可以比当前分配的字节数小或者大。如果比当前分配的小,那么多余的内存会还给堆,不能保证多余的内存会被清空。如果比当前分配的大,那么可能的话,就在紧挨着当前分配内存的区域分配新的内存,否则就会在堆的其他区域分配并把旧的内存复制到新区域。
如果大小是0而指针非空,那么就释放内存。如果无法分配空间,那么原来的内存块就保持不变,不过返回的指针是空指针,且errno
会设置为ENOMEM
。
该函数的行为概括在表2-2中。
表2-2:realloc
函数的行为
第一个参数 | 第二个参数 | 行为 |
---|---|---|
空 | 无 | 同malloc |
非空 | 0 | 原内存块被释放 |
非空 | 比原内存块小 | 利用当前的块分配更小的块 |
非空 | 比原内存块大 | 要么在当前位置要么在其他位置分配更大的块 |
在下例中,我们使用两个变量为字符串分配内存。一开始分配16字节,但只用到了前面的13字节(12个十六进制数字外加null
结束字符(0)):
char *string1;
char *string2;
string1 = (char*) malloc(16);
strcpy(string1, "0123456789AB");
接着,用realloc
函数指定一个范围更小的内存区域。然后打印这两个变量的地址和内容:
string2 = realloc(string1, 8);
printf("string1 Value: %p [%s]\n", string1, string1);
printf("string2 Value: %p [%s]\n", string2, string2);
输出如下:
string1 Value: 0x500 [0123456789AB]
string2 Value: 0x500 [0123456789AB]
图2-6说明了内存如何分配。
图2-6:realloc
示例
堆管理器可以重用原始的内存块,且不会修改其内容。不过程序继续使用的内存超过了所请求的8字节。也就是说,我们没有修改字符串以便它能装进8字节的内存块中。在本例中,我们本应该调整字符串的长度以使它能装进重新分配的8字节。实现这一点最简单的办法是将NUL
赋给地址507。实际使用的内存超出分配的内存不是个好做法,应该避免,指针的使用问题会详细讲解这一点。
在接下来的例子中,我们会重新分配额外的内存:
string1 = (char*) malloc(16);
strcpy(string1, "0123456789AB");
string2 = realloc(string1, 64);
printf("string1 Value: %p [%s]\n", string1, string1);
printf("string2 Value: %p [%s]\n", string2, string2);
执行以上代码得到类似下面的结果:
string1 Value: 0x500 [0123456789AB]
string2 Value: 0x600 [0123456789AB]
在本例中,realloc
必须分配一个新的内存块。图2-7说明了内存的分配。
图2-7:分配额外内存
评论前必须登录!
注册