【C语言】动态内存申请,堆空间与栈空间差异
我们在学习完C语言的数组后都会觉得数组长度固定很不方便,其实C语言的数组长度固定是因为其定义在栈空间,而栈空间的大小在编译时是确定的。如果使用的空间大小不确定可以使用堆空间。
#include <stdio.h>
#include <string.h>
#include <stdlib.h> //malloc\free使用的头文件
int main() {
int size; //所申请空间的大小
char *p;
scanf("%d",&size);
p=(char*)malloc(size); //申请空间
strcpy(p,"hello");
puts(p);
free(p); //释放空间
return 0;
}
malloc函数和free函数
//动态申请空间
void* malloc(unsigned int _Size);
//释放所申请的空间
void free(void *_Memory);
malloc 函数会动态申请 _Size 字节大小的堆空间,返回值为 void* 类型的指针(void* 类型的指针只能用来存储一个地址而不能进行偏移),malloc并不知道我们申请的空间用来存放什么类型的数据,所以要通过强制类型转换将 void* 类型转为所需类型。
free 函数的传入参数为 void* 类型,任何指针均可自动转换为 void* 类型。
申请堆空间时,内核中记录的是起始地址和大小,所以 free 函数要传入申请时的首地址进行匹配,而不能进行传入偏移后的地址。
堆空间与栈空间的差异
为什么要分栈空间和堆空间?
栈是计算机系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈\出栈操作都有专门的指令执行;
堆是C/C++函数库提供的数据结构,机制十分复杂,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索大小满足的空闲空间,如果没有找到,就有可能调用系统功能去增加程序数据段的内存空间。
显然,堆的效率比栈低得多。
栈空间由系统自动管理,堆空间的申请和释放需要自行管理。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//堆空间和栈空间的差异
char* print_stack() {
char c[20]="I am print_stack";
puts(c);
return c;
}
char* print_malloc() {
char *p;
p=(char*) malloc(20);
strcpy(p,"I am print_malloc");
puts(p);
return p;
}
int main() {
char *p;
p = print_stack(); //数据放在栈空间
printf("p=%s\n",p);
p = print_malloc(); //数据放在堆空间
puts(p);
free(p);
return 0;
}
执行结果:
为什么会打印 p=(null)?原因是 print_stack() 函数中的字符串存放在栈空间中,函数执行结束后,栈空间被释放,函数内的所有局部变量消失。而 print_malloc() 函数中的字符串存放在堆空间中,堆空间只有在执行 free 操作后才会释放,否则在进程执行过程中会一直存在。
本文来自博客园,作者:hzyuan,转载请注明原文链接:https://www.cnblogs.com/hzyuan/p/17961848
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)