动态内存管理
目录:
- 动态内存分配
- malloc
- free
- calloc
- realloc
=== =========================================
1.动态内存分配
动态内存分配的价值体现在进行时灵活性
常见的内存分配是在程序编译时确定的
inta=10;intarr[]={1,2,3};这样的定义,内存大小都是固定的,而且数组一旦确定便不能再调整,而有的时候我们所需要的内存大小是不确定的,这时我们可以通过一些函数来解决我们的问题
2.malloc
#include<stdlib.h>此时我们需要引入这个头文件
void*malloc(size_tsize);功能:向内存的堆区申请一块连续的空间,并返回指向这块空间的起始地址。
- 如果开辟成功,则返回起始地址
- 如果开辟失败,则返回NULL,因此一定要检查,如果要开辟的内存过大,可能超出计算机所能承受的范围此时就开辟失败了
- 返回值的类型为void*,所以malloc函数并不知道开辟空间的类型,可自行决定
- 如果参数size为0,malloc的行为是标准未定义的,取决于编译器。
#include<stdio.h>#include<stdlib.h>intmain(){intn=5;int*ptr=(int*)malloc(n*sizeof(int));//可以直接写数字if(ptr!=NULL){for(inti=0;i<n;i++){*ptr(i+i)=i;}for(inti=0;i<n;i++){printf("%d",*(ptr+i));}}return0;}我们通过强制类型转换,将malloc的返回类型转为int*
3.free
voidfree(void*ptr);free函数用来释放动态开辟的内存。
- 如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数ptr是NULL指针,则函数什么事都不做。
#include<stdio.h>#include<stdlib.h>intmain(){intn=5;int*ptr=(int*)malloc(n*sizeof(int));if(ptr!=NULL){for(inti=0;i<n;i++){*(ptr+i)=i+1;}for(inti=0;i<n;i++){printf("%d",*(ptr+i));}}free(ptr);ptr=NULL;return0;}为什么要将ptr置为空指针,free只释放内存,不改变指针自身,如果不将ptr置为空指针,那么它就变成了野指针,
4.calloc
void*calloc(size_tnum,size_tsize);函数的功能是num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0.
与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0
#include<stdio.h>#include<stdlib.h>intmain(){intn=5;int*ptr=(int*)calloc(n,sizeof(int));if(ptr!=NULL){for(inti=0;i<n;i++){printf("%d",*(ptr+i));}}free(ptr);ptr=NULL;return0;5.realloc
realloc的功能:让动态内存管理更加灵活。
有时我们会发现过去申请的空间太小了,有时又太大了,此时可以通过realloc来进行调整
void*realloc(void*ptr,size_tsize);- ptr是要调整的内存地址
- size调整之后新大小,单位是字节
- 返回值为调整后的起始位置**【如果后边的内存够用就延用后边的内存,如果不够那么就开辟一块新的堆】
- 这个函数调整原内存空间大小的基础上,还会将原来内存的数据移动到新的空间。
#include<stdio.h>intmain(){intn=5;int*ptr=(int*)malloc(n*sizeof(int));if(ptr!=NULL){for(inti=0;i<n;i++){*(ptr+i)=i+1;}for(inti=0;i<n;i++){printf("%d",*(ptr+i));}}printf("\n");int*p=NULL;p=realloc(ptr,n*sizeof(int));if(p!=NULL){ptr=p;for(inti=0;i<2*n;i++){printf("%d",*(ptr+i));}}free(ptr);ptr=NULL;return0;}