
在计算机领域,堆栈是一个不容忽视的概念,基本上使用了我们编写的C语言程序. 但是对于许多初学者来说,堆栈是一个非常模糊的概念.
堆栈: 一种数据结构,是程序运行时用于存储数据的地方. 这可能是许多初学者的理解c语言内存分配对应,因为我曾经认为它与汇编语言中的术语堆栈混淆. 我周围的许多编程朋友和我在Internet上看到的朋友都无法理解堆栈,因此我认为有必要在堆栈上分享我的观点. 如果有什么问题,请请朋友们多多指教,这对每个人都有很大帮助.
数据结构的堆栈
首先,我们需要了解数据结构中的堆栈. 尽管我们这样称呼,但是堆栈实际上是两种类型的数据结构: 堆和堆栈.
堆和栈都是数据结构,按顺序排列数据项.
堆栈就像存储数据的桶或盒子一样
让我们从您更熟悉的堆栈开始. 这是一种具有后进先出属性的数据结构,这意味着它先存储,然后再存储.
这就像我们要取出放置在盒子下面的东西(较早的对象)一样,我们首先需要移除按下的对象(较晚的对象).
那堆就像一棵倒置的树
由于堆的这一功能,通常用于实现优先级队列. 对堆的访问是任意的. 就像我们在图书馆的架子上拿书一样. 尽管书籍是按顺序排列的,但我们还是想取任何东西. 您无需像一stack书本一样把前面所有的书都拿出来. 书架的机制与盒子不同. 我们可以直接取出想要的书.
堆栈和堆中的内存分配

但是,我要谈的重点不在这里. 我要讨论的堆和堆栈不是数据结构的堆和堆栈. 堆栈区域不同,请注意.
我们来谈谈C语言程序的内存分配中的堆和栈. 在这里有必要提及内存分配. 不用担心通常,程序存储在Rom(只读存储器,例如硬盘)或Flash中,需要将其复制到RAM(随机存储器RAM)中执行. RAM将存储不同的信息,如下图所示:

如果内存中的堆栈区域位于相对较高的地址,并且地址增长方向朝上,则堆栈地址向下增加.
局部变量空间在堆栈中分配,堆区域向上用于分配程序员所应用的内存空间. 另外,还有一些静态区域分配静态变量和全局变量空间. 分配常量和程序代码空间的只读区域;和其他分区.
看一个上流行的经典例子:
main.cpp
1 int a = 0; //全局初始化区 2 char *p1; //全局未初始化区 3 main() 4 { 5 int b; //栈 6 char s[] = "abc"; //栈 7 char *p2; //栈 8 char *p3 = "123456"; //123456\0在常量区,p3在栈上。 9 static int c =0; //全局(静态)初始化区 10 p1 = (char *)malloc(10); //堆 11 p2 = (char *)malloc(20); //堆 12 }
0. 施用方法和回收方法不同
我不知道你是否了解一点.
堆和栈之间的第一个区别是应用方法: 栈(英文名称为stack)由系统自动分配,例如,我们定义了一个char a;系统将自动在堆栈上为其创建空间. 堆(英文名称为heap)是程序员根据其需求申请的空间,例如malloc(10);打开十个字节的空间.

由于堆栈上的空间是自动分配和回收的,因此堆栈上数据的生命周期仅在函数运行期间,并且在操作后释放,并且无法再次访问. 只要程序员不释放空间,就可以访问堆上的数据,但是缺点是,一旦忘记释放它,将导致内存泄漏. 还有其他一些区别. 我认为朋友总结的很好. 这是转述:
1. 申请后系统响应
堆栈: 只要堆栈的剩余空间大于请求的空间,系统就会为程序提供内存,否则它将报告异常并提示堆栈溢出.
堆: 首先,您应该知道操作系统有一个记录空闲内存地址的链表. 当系统从程序接收到一个应用程序时,它将遍历链接列表以查找第一个堆节点,该第一个堆节点的空间大于请求的空间,然后从空闲节点列表中删除该节点,并且该节点的空间为分配给程序. 此外,对于大多数系统,此分配的大小将记录在此存储空间的第一个地址处. 通过这种方式,代码delete语句可以正确释放内存空间. 另外,由于找到的堆节点的大小不一定与应用程序的大小完全相同,因此系统会自动将多余的部分放入空闲列表中.
换句话说,堆在应用后会做一些后续工作,这会导致应用效率问题.
2. 应用效率比较
基于点0和1.
Stack: 由系统自动分配,速度更快. 但是程序员无法控制.
堆: 它是new分配的内存,通常较慢,并且容易出现内存碎片,但是使用起来最方便.
3. 应用程序大小限制
堆栈: 在Windows下,堆栈是一个扩展为低地址的数据结构,并且是一个连续的内存区域. 这句话的意思是系统顶部确定了堆栈顶部的地址和堆栈的最大容量. 在WINDOWS下,堆栈的大小为2M(简而言之,为1M,这是在编译时确定的常数),如果当请求的空间超过堆栈上的剩余空间时,将提示溢出. 因此,堆栈中的可用空间很小.

堆: 堆是一种数据结构,可以扩展到更高的地址,并且是不连续的内存区域. 这是因为系统使用链接列表来存储空闲内存地址,该地址自然是不连续的,并且链接列表的遍历方向是从低地址到高地址. 堆的大小受计算机系统中可用的虚拟内存限制. 这表明堆获得的空间更加灵活,更大.
4. 堆和堆栈中的存储内容
由于堆栈的大小受到限制,子功能的使用仍然具有物理意义,而不仅仅是逻辑意义.
堆栈: 调用函数时,要压入堆栈的第一件事是主函数中的下一条指令(函数调用语句的下一个可执行语句)的地址,然后是该函数的参数. 在大多数C编译器中,参数是从右到左堆叠的,然后是函数中的局部变量. 请注意,静态变量不会被压入堆栈.
函数调用结束时,首先将局部变量弹出堆栈,然后弹出参数,最后堆栈上的顶部指针指向其最初存储的地址,这是主函数中的下一条指令,该程序将从那时开始继续运行.
堆: 通常,一个字节用于在堆的开头存储堆的大小. 堆中的特定内容由程序员安排.
5. 访问效率比较
char s1[] = "aaaaaaaaaaaaaaa"; char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaaaa在运行时分配;放在堆栈上.
bbbbbbbbbbbbb是在编译时确定的;放在堆里.
但是,在以后的访问中,堆栈上的数组比指针所指向的字符串(例如堆)要快.

例如:
#include void main() { char a = 1; char c[] = "1234567890"; char *p ="1234567890"; a = c[1]; a = p[1]; return; }
相应的汇编代码
10: a = c [1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov字节ptr [ebp-4],cl
11: a = p [1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov,byte ptr [edx + 1]
00401073 88 45 FC mov字节ptr [ebp-4],al
关于堆和栈之间差异的隐喻
堆和栈之间的区别可以从前辈的类比看出:
使用堆栈就像我们去餐厅吃饭一样,只需点菜(发出申请),付款并吃东西(使用),吃饱后就离开c语言内存分配对应,不需要注意食物的准备工作洗菜,洗碗等. 刷碗等扫地工作,他的优点是速度快,但自由度小.
使用堆就像制作自己喜欢的菜肴. 这比较麻烦,但是更符合您自己的口味,并且拥有更多的自由. 隐喻非常生动,单词很容易理解. 我不知道你是否有所收获.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-235180-1.html
作为正规小学毕业的人告诉泻教授