堆栈是一两种十分常用的数据结构,而在硬件中根据内存相关分区功能的不同,将和此两种数据结构功能相似的分区(不是物理意义上的分区)分别称之为堆区栈区,简称堆栈。

  • 所以要搞清楚不同之处(我刚学C语言的时候一直搞不清楚):堆栈在数据结构(软件)中来说是两种数据结构的名称;而在计算机内存中又表示两个不同的分区的名称

堆(Heap)

堆区在内存中占了相当大的一部分,这部分主要是为了储存程序中动态分配的数据,就C语言而言, malloc() realloc() calloc() 申请而来的空间就全部是堆中的空间,而动态申请的空间均需要利用 free() 手动释放掉。

当我们书写语句,在堆中申请空间:int* tmp = malloc(40 * sizeof(int)) ,可以计算出,我们申请的空间大小理论上应该为 \(40 \times 4 = 160\) ,但是其在堆中实际申请的空间应该是大于理论值一到两个字节的,而申请完毕后传回的指针实际上也不是申请空间的首地址,而是类似一个如下图所示的结构:

粗谈堆栈1.png
粗谈堆栈1.png

申请的实际空间如最大的红色边界线所示,而理论空间则如阴影部分所示,申请的空间最前面的一到两个字节(视底层的具体代码决定)用来标识由此开始的xx字节内存已被占用,以及一些必要的信息,来方便其他操作(例如需要 free() 之时,只需要将此标记移除或者改动即可)。

谈谈realloc() realloc() 进行内存扩展有两种方式:

  • 可以向后延拓之时,直接在此空间之后连续追加至相应的字节数即可
  • 无法延拓之时,寻找适合的位置,另辟空间,将原有的数据复制过去,返回新空间的指针

一个减小 malloc() 时间复杂度的方法: 将所有空闲的内存首地址之间利用链表连接起来,并注明此处闲余空间是多少,然后再次开辟之时,便可以直接跳转寻找合适的空间

栈(Stack)

栈是在程序运行时创立的一块内存,用于存放自动开辟的空间(在C语言中而言也就是声明的变量),其一般来说是可拓展空间的,可随着程序的执行自动进行扩展(就如同之前实现的那个栈一般)。

注意:

  • int* tmp = malloc(40 * sizeof(int)) 在堆中存储
  • int tmp[40] 在栈中存储

关于此块内存,也就是遵循着先进后出的原则,就是说:其是随着程序运行来对内存进行动态分配的 ,非常好理解,在次不多赘述。