在使用c语言编写代码解决问题时候,我们都会创建一系列变量,常量,表达式,语句,自定义函数来实现算法,解决问题。这些数据都会占用内存,在实现算法时,时间复杂度或空间复杂度低并且能够解决问题的算法就是好算法,我们每次开辟内存空间时候,多少都会有一些空间用不着,那么剩余的那块空间就浪费了。那么能不能我要用多大的空间自己开辟,后面不够就再添加空间,多了又减少空间,让内存空间完美的利用起来的方法呢?答案是有的,就是我们这一章节要讲的内容——动态内存分配。
? ? ? ? ? ? ? ? 动态内存分配的实现主要是动态内存分配函数实现。现在就让我们来见识一下这些函数。
1.malloc函数(所属string.h头文件)
注意事项:
1.如果开辟成功,则返回开辟好空间的指针。
2.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
3.返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
4.如果参数size为0,malloc的行为是标准未定义的,取决于编译器。
如下代码:
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
int *p=(int*)malloc(10*sizeof(int));
if(p=NULL)
{
printf("%s",strerror(errno));
}
else
{
int i=0;
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
return 0;
}
此段代码的意思是,使用malloc函数开辟10个整形元素动态内存空间,如果开辟失败返回空指针并且使用strerror函数配合errno打印出原因,若开辟成功吧存放在*(P+1)地址的整形元素打印出来。
那么开辟空间有可能失败吗?什么情况下会失败呢?
如下代码:
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
int *p=(int*)malloc(INT_MAX);
if(p=NULL)
{
printf("%s",strerror(errno));
}
else
{
int i=0;
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
return 0;
}
这里的代码与上段代码只有一个地方不同,就是malloc函数的参数改为INT_MAX,这个标识符返回的是int类型的最大值(不清楚的道友可以百度一下),想一下int类型占4个字节,也就是32位,最大值就是2的32次方,这个数得有多大,吧这个数再转换为这么多个数的整形空间,你的内存条能开辟这么大的空间吗?显然不能,所以要谨慎开辟空间。
2.free函数(所属stdlib.h头文件)
? ? ? ? 这个函数是与malloc函数配对使用的,当然基本涉及到动态内存开辟都要用到此函数,为什么都要用到呢?让在下来阐述一下吧。
? ? ? ? 想一想,我们在编写程序时,这些代码多多少少都要占用内存空间,那么我们每次运行完代码后,就让我们的代码像一个山大王一样一直占领着那块内存空间吗?要是一两个还可以容纳,要是每个代码都像这样占山为王,那我们平时这些内存条常见4个G,8个G,最多好像就16个G,够这些代码折腾吗?系统其他数据就不需要存放在内存空间呢吗?显然是不行的,这些空间是我们向操作系统申请得到的,我们借了人家的东西就得有借有还,你要是不还,操作系统就会强行收回这块内存空间(这是属于我们编译器申请开辟空间),每次程序结束后,操作系统都会自动收回这次所运行程序占用的空间。
? ? ? ? 那么我们动态内存开辟不属于编译器帮你申请空间,而是自己申请开辟空间,那么我们这时候怎么将运行完程序后的空间还给操作系统呢?这就要用到我们的这个函数——free
如下代码:
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
int *p=(int*)malloc(10*sizeof(int));
if(p=NULL)
{
printf("%s",strerror(errno));
}
else
{
int i=0;
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
free(p);
p=NULL;
return 0;
}
这段代码先是使用malloc函数申请了10个整形的空间,假设开辟成功,然后咔咔运行完了,然后咱们借了人家的空间,就要还给人家,使用free函数吧存放在p的动态内存空间还给操作系统。到了这了就有人疑问为什么最后还要吧p着个指针置为空指针,这是一个安全问题,你虽然把p指针的内存空间释放了,但是p指针还记得到那块内存空间的地址,那么是不是就会导致有些不好的人利用这个指针找到那块内存空间呢?这时候为了解决这个安全问题,我们通常会把这个指针来上一闷棍让他失忆(赋值空指针),让他不记得那块空间的地址,是不是就很好的解决了这个问题呢?