C realloc函数

我们可能需要时不时地增加或减少为指针分配的内存,如果需要一个变长数组这种做法尤其有用,数组会讨论这一点。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:分配额外内存

赞(3)

评论 抢沙发

评论前必须登录!

 

C指针