在内存中有一个称为堆栈的部分,它从顶部开始并向下增长到堆。这个堆栈和 LIFO 堆栈是一样的吗?底部的堆是 FIFO 吗?
当您执行“push”和“pop”时,是否会改变内存中的堆栈?
在内存中有一个称为堆栈的部分,它从顶部开始并向下增长到堆。这个堆栈和 LIFO 堆栈是一样的吗?底部的堆是 FIFO 吗?
当您执行“push”和“pop”时,是否会改变内存中的堆栈?
是的,计算机体系结构使用 LIFO 堆栈来存储诸如返回地址、局部变量等内容。来自Wikipedia:
x86 架构具有对执行堆栈机制的硬件支持。push、pop、call 和 ret 等指令与正确设置的堆栈一起使用,以传递参数、为本地数据分配空间以及保存和恢复调用返回点。ret size 指令对于实现空间高效(和快速)调用约定非常有用,其中被调用者负责回收参数占用的堆栈空间。
例如,当一个函数被调用时,架构将返回地址、当前寄存器值等压入堆栈。当函数返回时,该数据会从堆栈中弹出,因此可以在之前的位置继续执行。
这是一大堆内存,但是有一个堆栈指针指向堆栈的顶部。推时上升,弹出时下降。但通常你可以通过修改指针来作弊,这样你就可以得到一个已经弹出的值。
并非所有架构的堆栈都朝着相同的方向发展。最后一点都不重要。一些系统使堆栈指针在 push 时增加,在 pop 时减少,其他系统在 push 时减少,在 pop 时增加。
示例:堆栈指针位于 0x100,它是一个递增系统。然后你推,堆栈指针在 0x104。你再次推动,在 0x108。你弹出,回到 0x104。另一个系统将从 0x100 开始,向下推到 0xfc,然后向下推到 0xf8,然后弹回到 0xfc。如果你再次弹出,你会回到 0x100。如果然后从堆栈指针中减去 8,它会回到 0xf8,因此您可以再次弹出它们。(或者,C 编译器在函数末尾会做什么,只需从堆栈指针中添加/减去 12,而不是在 3 条指令中弹出 3 个局部变量。
我不确定您所说的“实际上是一个堆栈”是什么意思(什么是“真正的”堆栈?),但它在概念上是一样的:push
递减“堆栈指针”,然后pop
递增它。
您所说的“堆栈”是程序的调用堆栈,因此从这个意义上说,它是一个堆栈。但是没有必要这样:实际的实现是特定于硬件、操作系统和语言运行时的——我使用了 C 编译器,其中调用堆栈被实现为堆栈帧的 [双重] 链表,分配在堆,类似于 IBM 大型机操作系统的处理方式。
Intel/Windows 风格的固定大小硬件堆栈的缺点是它使环境对递归不太友好。OTOH,它使堆栈的增长非常有效,因为您不必使用操作系统资源来分配堆外的内存:它只是增加一个指针。