C语言堆和栈的区别是什么?

一、问题

栈是存放函数的所有动态局部变量及函数调⽤和返回有关信息的⼀块内存。它为调试程序提供了⼀种功能,能够显示⼀个已被调⽤的函数的列表,这是调试程序时⼀种很有⽤的⼿段。

堆提供 malloc( ) , calloc( ) 和 realloc( ) 等函数获取内存空间的⼀块内存。下⾯采⽤对⽐的形式分别介绍堆和栈的作⽤,以及它们的区别。

二、解答

1. 堆和栈的作⽤

(1)栈的内存管理严格遵循先进后出的顺序,即释放栈中对象所占内存时的顺序刚好与为这些对象分配栈中内存时的顺序相反,这⼀点正是实现函数调⽤所需要的。从栈中分配内存效率特别⾼,C语⾔编译程序能产⽣如此好的代码的原因之⼀就是充分利⽤了栈。

(2)从堆中获取内存⽐从栈中获取内存要慢得多,但是堆的内存管理却⽐栈灵活得多。任何时候都可以从堆中获取内存,⽽且在释放堆中对象所占内存时,可以按任意顺序进⾏。数据对象使⽤栈中内存⽐使⽤堆中内存程序运⾏更快。但是,有时候使⽤堆中内存可以改善⼀种算法,从⽽使它更快,或者更灵活,因此使⽤堆或栈要折中考虑。

2. 堆和栈的区别

在了解了堆和栈各⾃的⽤途后,从两者的申请⽅式、申请后系统的响应、申请⼤⼩的限制、申请效率的⽐较和存储内容各⽅⾯了解它们的实质区别。

(1)申请⽅式

栈是由系统⾃动分配。如声明在函数中的⼀个局部变量 "int i;",系统会⾃动在栈中为 i 开辟内存空间。⽽堆是程序员⾃⼰申请,同时指明⼤⼩。在C语⾔中,堆提供 malloc( ) ,calloc( ) 和 realloc( ) 等函数获取内存空间的⼀块内存,如 " buffer=(int*)malloc(256) "是为 buffer 分配了⼀个256 字节⼤⼩的 int 型内存空间。

(2)申请后系统的响应

只要栈的剩余空间⼤于所申请空间,系统将为程序提供内存,否则将报异常,提示栈溢出。⽽堆则是⾸先确定操作系统有⼀个记录空闲内存地址的链表。当系统收到程序的申请时,会遍历此链表,寻找第⼀个⼤于所申请空间的堆结点, 然后将该结点从空闲结点链表中删除,并将该结点的控件分配给程序。

(3)申请⼤⼩的限制

在 windows 下,栈是向低地址扩展的数据结构,是⼀块连续的内存区域。它的最⼤容量是预先规定好的,如果申请的空间超过栈剩余的空间,将会提示溢出,能从栈获得的空间较⼩。⽽堆是向⾼地址扩展的数据结构,是不连续的内存区域。

这是因为系统是⽤链表来存储空闲内存地址的,⽽链表的遍历⽅向是由低地址向⾼地址, 堆的⼤⼩受限于计算机系统中有效的虚拟内存。因此,堆获得的空间⽐较灵活,也⽐较⼤。

(4)申请效率

在申请⽅式中,已经得知栈是由系统⾃动分配的,速度⽐较快,不容易控制。⽽堆是由 new 分配的内存,速度⽐较慢,⽤起来较⽅便。

(5)存储内容

在函数调⽤时,第⼀个进栈的是主函数中的下⼀条指令(函数调⽤语句的下⼀条可执⾏语句)的地址,然后是函数的各个参数。在⼤多数 C 编译器中,参数是由右往左⼊栈的,然后是函数中的局部变量。

注意,静态变量是不⼊栈的。当本次函数调⽤结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是 主函数中的下⼀条指令,程序由该点继续运⾏。⽽堆⼀般是在堆的头部⽤⼀个字节存放堆的⼤⼩,堆中的具体内容由程序员安排。

三、总结

通过对栈和堆的⽐较,⼤致了解了堆和栈的区别,以及⽤途。其实,栈和堆的关系可以理解为机洗⾐服和⼿洗⾐服。全⾃动洗⾐机洗⾐服,将所有的脏⾐服放进去,倒上⽔, 放上洗⾐液就可以了。这样很便捷,但是灵活度和⾃由度较⼩。⼿洗⾐服虽然很累,但是可以将⾃⼰认为⽐较脏的局部地⽅多洗洗或分类洗,灵活度较⼤。

相关推荐
Scott9999HH9 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社10 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海10 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖11 小时前
JDK 26 新特性详解
java·开发语言
马优晨11 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区13 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai14 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜14 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa14 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio