目录
一、为啥要申请动态内存?
我们了解学过的:
各种类型变量的声明,数组的声明,再创建时都是会申请一定的空间(内存),但是都是在栈区上申请的
第一个 向栈区申请4个字节的空间
第二个 向栈区申请5*4 = 20个字节的空间
但是,这样在栈上申请开辟的空间大小是固定的,然而数组在声明时必须确定大小,这样限制了数组只能这么大,后续需要更大的空间时,无法满足这一个要求;(当然提一嘴,🐸🐸c99支持了变长数组,也就是说数组里面的元素个数可以是变量,遗憾的是VS不支持🤷♂️🤷♂️)
可是,有时候我们需要的空间⼤⼩在程序运⾏的时候才能知道,这个时候怎么办呢???就此就有了动态内存的申请的用武之地; 可以让程序员灵活开辟和销毁空间。
二、内存申请函数
申明一下:(头文件 <stdlib.h>)
有关内存的情况,都是以字节为单位进行的,所以下面的空间申请也是以字节为单位向内存申请空间,而下面向内存申请的一块空间是连续的,有没有发现和数组很像??其实类似于数组,但是数组是向栈区申请固定空间,然而内存函数就是向内存申请一个可变化大小的空间,但是不同内存函数之间又有着不小的差别
1、malloc函数:
向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针其中size是元素大小;但是返回viod指针,所以可以为各种类型数据申请空间,自己去定义需要的类型,但是需要用个强制内型转换
以char型为例:相当于申请一个char型数组arr[5];(前面乘了5就是申请5个size(type)大小的元素)
如下图:向内存申请一块空间;
返回的是指针
失败则是返回空指针(NULL);
成功指向开辟好空间的指针;
如果参数 size 为0,malloc的⾏为标准是未定义的,取决于编译器
2、calloc函数:
向空间申请num个大小为size的元素( 也就是一个数组),并把每个字节初始化为 0;
一个字节:
3、realloc函数:
让空间申请更加灵活,可以修改空间的大小,返回的是调整之后的起始位置;str接受需要调整内存的地址,size是需要调整的空间大小,也就是你原本空间是20,你需要40字节的空间,那么你就申请40,他会给你的空间从20字节的空间变成40字节的空间
申请成功的话,调整空间有2种情况:
情况1: 直接原地址扩容
情况2:拷贝原地址内容到新地址扩容空间大小——异地扩容
!!!!异地扩容会将原空间进行销毁
有一个写法:这个相当于上面malloc的例子,传的空地址,此时相当于向内存申请一个空间来使用,而不是调整一个空间大小,等价于malloc
失败则是返回空指针(NULL);
成功指向开辟好空间的指针;
如果参数 size 为0,malloc(realloc)的⾏为是标准是未定义的,取决于编译器
4、free函数:
动态内存的释放和回收,未释放可能存在内存的泄露 "内存泄露"
释放的是起始位置,注意一定要传起始地址(我们申请空间下来,我们拥有了这个空间是使用权限,你只有使用权限,肯定是要还回去的,住酒店到时间了还得退房;free相当与将使用权限 还给操作系统)
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。(不能释放非动态开辟空间)
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
回收权限以后,接受动态内存的指针会变成野狗(野指针),我们要给它栓起来(赋值空指针 )
注意:虽然若是没有释放,当程序结束时会由操作系统进行释放,但是还是要尽量去使用free释放,我们要告诉别人需要释放,因为你不退出,这个内存一直占着茅坑不拉屎,不是浪费资源么,所以一定要去释放!!!!!!
5、代码实现一下:
说一下,malloc 、calloc、realloc函数都要有的操作步骤
你申请了空间,有可能会失败,若是失败呢就是空指针,对于空指针是不能进行操作的,所以需要判断一下是否为空!!!看下面代码即可;
malloc:
int main()
{
char* arr = (char*)malloc(5*sizeof(char));
if (arr == NULL)
{
perror("malloc");
return 1;
}
free(arr);
arr = NULL;
return 0;
}
return 1:表示提前结束的意思,你都申请失败了那么我们就只好提前结束了
perror函数:用于在发生系统调用错误时输出有关错误信息的描述。
calloc:
int main()
{
char* arr = (char*)calloc(5,sizeof(char));
if (arr == NULL)
{
perror("calloc");
return 1;
}
free(arr);
arr = NULL;
return 0;
}
realloc:
int main()
{
char* arr = (char*)calloc(5, sizeof(char));
if (arr == NULL)
{
perror("calloc");
return 1;
}
//arr要是首元素地址,额外创建一个指针来接受realloc,因为如果realloc申请失败,则会返回空指针,但是arr是有值的
char* ctr = realloc(arr, 10 * sizeof(char));
if (ctr == NULL)
{
perror("realloc");
return 1;
}
arr = ctr;
//释放空间
free(arr);
arr = NULL;
return 0;
}