C语言进阶系列|超详细的C进阶教程!(五)动态内存管理
作者的码云地址:https://gitee.com/dongtiao-xiewei
后续作者会更新力扣的每日一题系列,原代码会全部上传码云,推荐关注哦,笔芯~
还像更深入地了解c语言?快来订阅作者的c语言进阶专栏!作者承诺本系列不会TJ!预计更新:指针,字符串处理,内存管理,结构体,预处理等等我们在以前的文章中提到,其实计算机的内存分为以下三个区
- 栈区:用于存放临时变量,形式参数
- 堆区:用于动态内存管理
- 静态区:用于存放静态变量,全局变量等
一般来说,堆区的空间比栈区要大,堆区大约有几个G的内存而栈区可能只有几百M
目录
- 引例
- 动态内存函数介绍
-
- malloc函数
- calloc函数
- free函数
- realloc函数
- 总结与提示
引例 为什么会存在动态内存分配?
比如,我们要实现这种变长数组
int n=0;
scanf("%d",&n);
int a[n]={
0};
这个数组的长度在使用前我们是不知道的,所以用一个变量来代替
但是,这个代码并不一定在所有编译器上都能编译成功,所以导致了一个可移植性的问题
但用动态内存管理,就能解决变长数组的跨平台问题了
int n=0;
scanf("%d",&n);
int* arr=(int*)malloc(sizeof(int)*n);
这个代码可以在堆区开辟n个整型的空间
亦或者,比如力扣第一题
文章图片
我们需要返回一个int*,也就是一个整型数组
但返回方式就只能先在堆上开辟空间,进行修改后再返回这一块空间起始位置的指针
因为,在函数内开辟的数字,出了函数是要销毁的,所以不能直接返回
所以,动态内存管理是C语言一个重要的部分
而要介绍这一章的内容,核心是以下的几个函数
注意,动态内存函数需要头文件!
动态内存函数介绍 malloc函数 函数有一个参数,代表需要开辟空间的大小,单位字节
【C语言进阶系列|超详细的C进阶教程!(五)动态内存管理】这个函数的功能是在堆上开辟一块连续的空间,函数返回一个void指针,指向这块空间的起始位置
int* arr = sizeof(20);
开辟20字节的空间,由int接受
但你需要注意:这个函数的返回类型是void*类型,万能接受指针,使用前最好强制类型转换一下,与数组类型匹配
int* arr = (int*)sizeof(20);
如果此函数开辟失败,则返回一个NULL指针
所以,在使用空间前,一定要检查有效性
int main()
{ int* arr = (int*)malloc(20);
if (!arr)
{printf("fail\n");
exit(-1);
}
else
{//操作
}
return 0;
}
有什么情况会返回失败呢?
当然有,你开辟的空间过大,将会开辟失败!
calloc函数 这个函数有两个参数,第一个参数代表开辟的元素个数,第二个参数代表每个元素占的字节数
另外,这个函数会自动将这块空间初始化为0,但malloc不会
以下两个数组是等价的
int arr[10] = {
0 };
int* arr1 = (int*)calloc(10, sizeof(int));
free函数 这个函数的参数是一个地址,可以将指向的这块动态管理的空间释放掉
使用示例:
int main()
{ int* arr = (int*)malloc(20*sizeof(int));
if (!arr)
{printf("fail\n");
exit(-1);
}
else
{//操作
}
return 0;
}
free(arr);
arr=NULL;
//这步有必要吗
最后一句虽然可以去掉,但这个语句却非常重要
因为将空间释放掉了,这块空间就还给操作系统了就不属于我们了!这个指针也成了俗话说的野指针!
所以,最后一句可以防止野指针问题
我们在编程中,为了防止内存泄露,在此空间使用完成后,必须及时释放掉!
realloc函数 这个函数两个参数,第一个为一个数组,第二个是一个大小
这个函数的功能是将原数组调整到指定大小!
使用示例
注意:需要一个中间变量来交换**(会自动将原数组数据拷贝),同样需要检查有效性**
int main()
{ int* arr = sizeof(20);
if (!arr)
{printf("fail\n");
exit(-1);
}
int* tmp = realloc(arr, 100);
if (!tmp)
{printf("fail\n");
exit(-1);
} else
{arr = tmp;
//操作
}
return 0;
}
完整的动态空间使用示例
int main()
{ int* arr = (int*)malloc(sizeof(int) * 10);
if (!arr)
{printf("fail\n");
exit(-1);
}
for (int i = 0;
i < 10;
i++)
{arr[i] = i;
printf("%d ", arr[i]);
}
int* tmp = (int*)realloc(arr, 20 * sizeof(int));
if (!tmp)
{printf("fail\n");
exit(-1);
}
arr=tmp;
for (int i = 11;
i < 20;
i++)
{arr[i] = i;
printf("%d ", arr[i]);
}
free(arr);
arr = NULL;
tmp = NULL;
return 0;
}
输出结果
文章图片
总结与提示
- 使用动态空间时一定要检查空间开辟是否成功
- 你最好不要越界访问,对程序没有什么好处
- 不要去尝试对非动态开辟内存执行free函数
- free这块空间时,严禁修改指向这块空间的指针值
推荐阅读
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- 【欢喜是你·三宅系列①】⑶
- 一起来学习C语言的字符串转换函数
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- C语言浮点函数中的modf和fmod详解
- C语言中的时间函数clock()和time()你都了解吗
- 你不可不知的真相系列之科学
- 人脸识别|【人脸识别系列】| 实现自动化妆
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)