栈和栈帧的基本理解

栈(Stack)是一种数据结构,遵循“后进先出”(LIFO,Last In, First Out)的原则。在函数调用、表达式求值、内存管理等场景中。栈帧(Stack Frame)则是栈中的一个基本单位,用来存储函数调用的上下文信息。

image.png

栈(Stack)

栈是一种线性数据结构,只允许在一端进行操作,这一端称为“栈顶”(Top)。主要的操作包括:

  • 压栈(Push):将一个元素放入栈顶。
  • 弹栈(Pop):从栈顶移除一个元素。
  • 查看栈顶元素(Peek):检查栈顶的元素但不移除它。

栈的应用:

  • 函数调用管理:当一个函数被调用时,它的执行信息被保存到栈中,这样在函数返回时,可以继续执行之前的代码。
  • 递归处理:递归函数每次调用自身时都会在栈上创建一个新的栈帧,从而保存每次调用的状态。

栈帧(Stack Frame)

栈帧是栈中的一个片段,每次函数调用时,都会在栈中创建一个新的栈帧。栈帧用来存储函数执行所需的局部变量、参数、返回地址以及其他状态信息。一个栈帧通常包含以下部分:

  1. 返回地址:指示函数返回时,程序应该继续执行的位置。
  2. 函数参数:传递给函数的参数值。
  3. 局部变量:函数内部定义的变量。
  4. 保存的寄存器值:在调用函数之前保存的寄存器状态,以便函数返回时恢复。
  5. 栈指针和基指针:ESP(栈指针,Stack Pointer)和 EBP(基指针,Base Pointer)分别指向栈的顶部和当前栈帧的底部,用来管理栈帧。
栈帧的工作原理

当程序调用一个函数时,系统会执行以下步骤:

  1. 保存返回地址:调用者的程序计数器(Program Counter,PC)保存到当前栈帧中,以便函数结束后能够返回到调用者的位置。
  2. 为函数创建新的栈帧:系统会在栈顶为被调用的函数分配一个新的栈帧。
  3. 保存寄存器状态:调用者的寄存器状态保存到新栈帧中。
  4. 传递参数和保存局部变量:函数参数传递到新的栈帧,并在其中分配局部变量的空间。
  5. 执行函数:函数执行其代码,当遇到 return 或到达函数末尾时,函数返回。
  6. 恢复状态:从栈中弹出当前栈帧,恢复调用者的寄存器状态和返回地址,程序继续执行。

例子说明

void foo(int a, int b) {
    int c = a + b;
}

int main() {
    foo(5, 10);
    return 0;
}

执行 foo(5, 10) 时,栈和栈帧的变化如下:

  1. 调用 foo
    • 在栈顶创建新的栈帧。
    • 保存 main 函数的返回地址。
    • 将参数 5 和 10 压入栈帧。
    • 将 foo 函数的返回地址压入栈帧。
  2. 执行 foo
    • 在栈帧中为局部变量 c 分配空间。
    • 执行 c = a + b;。
    • 完成后,准备返回。
  3. 返回到 main
    • 弹出 foo 的栈帧。
    • 恢复 main 的状态,程序继续执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值