一.realloc()函数简介
我们先来看一下cplusplus.com - The C++ Resources Network网站上realloc()函数的基本信息:
1.函数功能
可以看到,realloc()函数的功能是:更改动态分配的内存大小.
即便将内存块移动到新位置(异地扩容),之前内存块的内容也会随之转移到新的位置.但新开辟的部分是未被初始化的.
如我们使用malloc开辟并初始化5个整型,然后使用realloc扩容到10个整型后打印:
2.函数参数
该函数一共有2个参数,分别是:
void* realloc (void* ptr, size_t size);
1>.void* ptr
第一个参数的类型是无类型指针(void*),它指向一个要重新分配内存的内存块,该内存块是之前通过调用malloc,calloc或realloc进行动态分配内存的.
如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针.
2>.size_t size
第二个参数的类型是无符号整型(size_t),它表示新内存块的大小,以字节为单位.
如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。
3.函数返回值
void*
函数的返回值类型是无类型指针(void*),它的作用是在函数运行结束后返回指向重新分配大小的内存块的指针.如果请求失败了,则会返回一个空指针.
4.函数头文件
该函数包含在头文件<stdlib.h>中.
二.realloc()函数的具体使用
realloc()函数的使用场景是:当我们想调整先前使用malloc(),calloc()或realloc()函数开辟的动态内存的大小时,我们可以使用realloc()函数来实现这一诉求.
1.使用realloc()函数完成动态整型数组空间的扩容
如下,我们使用realloc()函数调整一个有10个元素的整型数组的大小将其改为15个整型元素.
分别给realloc()函数传入:动态开辟的内存块指针(即p),新内存块的大小(即15*sizeof(int)).
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() { int* p = (int*)malloc(10*sizeof(int)); //开辟10个整型大小空间 if (p == NULL) //如果开辟失败,则打印错误原因 { //打印错误原因的一个方式 printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 10; i++) //遍历并初始化打印这10个整型空间 { *(p + i) = i; printf("%d ", *(p + i)); } //可以正常使用p指针来操作这片空间了 } printf("\n"); int* p2 = (int*)realloc(p, 15 * sizeof(int));//将这块空间扩容到15个整型 if (p2 == NULL) { printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 15; i++) //遍历并打印这15个整型空间 { *(p2 + i)=i; printf("%d ", *(p2 + i)); } } free(p); //释放p的内存空间 p = NULL; //将指针p置为NULL,防止其变成野指针 return 0; }
在vs编译器中运行查看结果:
可见realloc()函数成功的将malloc()函数开辟的10个整形大小的空间改为15个整型大小的空间了.
2.使用()函数完成动态结构体空间的扩容
创建好结构体变量后,我们给calloc()函数传入:3 , sizeof(PeoInfo)(即3个PeoInfo类型大小的字节数).用来开辟好3个PeoInfo大小的结构体数组.
使用calloc()开辟好空间后我们使用realloc()函数将结构体数组的空间扩容到5个.
给realloc()函数传入:ptr , 5*sizeof(PeoInfo)(即5个PeoInfo类型大小的字节数).
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> //人的信息-结构体 typedef struct PeoInfo { char name[20]; int age; char sex[5]; char addr[20]; char tele[11];//电话11位,留一位给'\0'; }PeoInfo; typedef struct Contact { PeoInfo* data; //存放人的信息 int sz; //用来记录当前已经存放的信息的个数 int capacity; //记录当前通讯录的最大容量 }Contact; int main() { Contact con; PeoInfo* ptr = (PeoInfo*)calloc(3, sizeof(PeoInfo)); //动态开辟空间 if (ptr == NULL) //如果开辟失败,则打印错误原因 { perror("InitContact::calloc"); return; } PeoInfo*ptr2 = (PeoInfo*)realloc(ptr, 5 * sizeof(PeoInfo)); if (ptr2 == NULL) { perror("InitContact::realloc"); return; } free(ptr2); //使用完后向系统归还动态开辟的内存空间 ptr2 = NULL; //将ptr2指针置为空,避免ptr2成为野指针 return 0; }
在vs编译器中查看结果:
可见realloc()函数成功的将结构体的元素个数由3个改为了5个.
三.realloc()的异地扩容
使用realloc()函数调整内存空间存在两种情况:
- 原有空间之后有足够大的空间
- 原有空间之后没有足够大的空间
如:图中绿色空间是我们之前动态开辟的内存空间,而现在我们想使用reallo函数将它扩容一倍,
黑色条代表内存条,红色空间代表被其他程序占用的空间,而紫色空间代表待扩容空间.
情况一:
当是情况一的时候,要扩展内存就原有内存之后直接追加空间,原来空间的数据不发生变化.
情况二:
当情况二的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址.
结语
希望这篇realloc()函数详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.
有关更多动态开辟相关知识可以移步:
学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!
C语言动态内存开辟相关库函数思维导图: