动态内存开辟函数malloc,calloc,realloc和free
1.malloc和free函数2.calloc函数3.realloc函数我们在向内存申请空间时,一般有如下几种方式:
//第一种:int main(){int a=10;//申请4个字节,一小块一小块申请}//第二种int main(){int arr[10];//申请40个字节,一大块一大块申请}
这两种方式开辟的空间是固定的,不能变化的。但是对于空间的需求,不仅仅是上述情况,有时候我们需要的空间大小在运行程序的时候才知道。
接下来介绍动态内存函数malloc,calloc,realloc和free,以满足我们对内存的需要。
动态申请的内存在内存的堆区
注意:他们都是库函数,使用时需要引用头文件<stdlib.h> !!!
1.malloc和free函数
首先介绍动态内存开辟函数malloc和free
函数原型为:void *malloc(size_t size)
参数:需要开辟的空间大小,单位字节。
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针(这块空间的首地址)。
如果开辟成功,则返回一个指向开辟好空间的指针如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。返回类型是void*,所以这个函数不知道开辟空间的类型,具体使用时强制类型转换成需要的类型。free函数是与malloc,calloc,realloc匹配使用的函数,在程序结束时用来释放开辟的空间,防止内存泄漏。
函数原型为:void free( void *p );
意思是释放p所指向的空间。
注意:free必须释放的是动态开辟出来的空间!!
以下是他们的使用方法:
#include "stdio.h"#include "stdlib.h"#include "string.h"#include "errno.h"int main(){int arr[10]={0};int *p=(int*)malloc(40);//向堆区开辟了40个字节//int *p(int*)malloc(INT_MAX+1);//开辟失败时//判断,检查,防止开辟失败if(p==NULL){printf("%S\n",strerror(errno));//提示错误信息return 1;//结束运行}//使用int i=0;for(i=0;i<13;i++) {*(p+i)=i; }//打印for (i = 0; i < 13; i++){printf("%d ", *(p + i));}//释放free(p);//此时只是释放了开辟的40个字节,但是变量p内仍然保留原地址,如果这时有人使用了p,这时p是十分危险的,这是一个野指针!!所以要把p置空。p=NULL;return 0;}
开辟成功时运行结果是:
开辟失败时运行的结果是:
2.calloc函数
接下来介绍另一个动态内存开辟函数calloc
函数原型为:void *calloc(size_t num,size_t size)
参数是:开辟类型的个数,开辟类型的大小。
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针(这块空间的首地址)。
功能是为num个大小为size的元素开辟一块空间,并且空间里每个字节自动初始化为0。与函数malloc的区别只在于calloc会在返回地址之前把申请空间里的每个字节初始化为0。如果开辟成功,则返回一个指向开辟好空间的指针
如果开辟失败,则返回一个NULL指针,因此calloc的返回值也要做检查。
返回类型是void*,所以这个函数不知道开辟空间的类型,具体使用时强制类型转换成需要的类型。
使用方法如下:
#include "stdio.h"#include "stdilb.h"#include "string.h"#include "errno.h"//开辟10个整型空间int *p=(*int)calloc(10,sizeof(int));//检查判断if(p==NULL){printf("%s\n",strerror(errno));return 1;}//使用int i=0;for(i=0;i<10;i++){*(p+i)=i;}//打印for(i=0;i<10;i++){printf("%d ",*(p+i));}//使用完后要释放free(p);p=NULL;return 0;
成功开辟运行后的结果是:
验证其开辟空间后自动初始化为0的代码是:
int main(){int* p = (int*)calloc(10, sizeof(int));if (p == NULL){printf("%s\n", strerror(errno));return 1;}int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;}
运行后的结果是:
3.realloc函数
最后介绍动态内存调整函数realloc
函数原型:void realloc(void ptr,size_t size)
参数:ptr是要调整的内存地址,size是调整之后的新大小
如果调整成功,则返回一个指向调整后空间的指针
如果调整失败,则返回一个NULL指针,因此calloc的返回值也要做检查。
返回类型是void*,所以这个函数不知道开辟空间的类型,具体使用时强制类型转换成需要的类型。
![在这里插入图片描述](http://zhangshiyu.com/zb_users/upload/2024/05/20240515114511171574471178690.jpg)
如上图所示,
情况1为在调整内存空间大小时后面的内存被占用,此时不会再向后调整以致覆盖被占用的内存,而是会重新寻找一块大小合适的内存进行调整,这时ptr指向的是调整后新内存的地址,并且原空间里的数据会自动复制到新空间,原空间也会自动销毁。
情况2是在调整内存空间大小时后面的内存足够,此时直接调整即可。
使用方法如下:
int main(){int* p = (int*)malloc(40);if (p == NULL){printf("%s\n", strerror(errno));return 1;}//使用int i = 0;for (i = 0; i < 10; i++){*(p + i) = i + 1;}//扩容int* ptr = (int*)realloc(p, 80);//不要直接使用p接收,防止调整失败if (ptr != NULL){p = ptr;}for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;}
调整成功后的运行结果是: