关于栈

一、栈的布局

// C 代码
void myFunc() {
    int a; // 步骤2:在栈帧中为 a 预留空间(比如在 SP+4 的位置)
    int b; // 步骤2:在栈帧中为 b 预留空间(比如在 SP+8 的位置)
    a = 10; // 步骤3:将值 10 MOV 到 [SP+4] 这个内存地址
    b = 20; // 步骤3:将值 20 MOV 到 [SP+8] 这个内存地址
}
void func1() { func2(); } // func1 先“入”
void func2() { }          // func2 后“入”
// 返回时:func2 先“出”,func1 后“出”

正确的内存地址布局(高→低)
正确的栈增长方向(向下)
正确的变量存储顺序(后定义的地址高)
正确的栈指针位置(指向栈顶)
image

二、什么是先入后出

===============================================
        情况1:您的图片(单个函数内部)
===============================================
高地址 | 调用者(如main函数)的栈帧 |
      |-----------------------------| ← 栈帧边界
      | 局部变量 b  (地址较高)       | ← 同属func1
      | 局部变量 a  (地址较低)       | ← 同属func1
      |-----------------------------| ← SP (栈顶)
低地址 |                            |
===============================================
说明:func1函数内,a和b是“室友”关系,同时入住,同时退房。

===============================================
        情况2:函数调用(先入后出)
===============================================
1. main函数调用func1:
高地址 | main函数的局部变量        |
      |-----------------------------| ← 调用func1前的SP
      | func1的返回地址             | ← func1“入栈”
      | func1的栈帧(包含a, b)       |
      |-----------------------------| ← func1执行时的SP
低地址 |                            |

2. func1调用func2:
高地址 | main函数的局部变量        |
      |-----------------------------|
      | func1的返回地址             |
      | func1的栈帧(包含a, b)       |
      |-----------------------------| ← 调用func2前的SP
      | func2的返回地址             | ← func2“入栈”
      | func2的栈帧(包含c, d)       |
      |-----------------------------| ← func2执行时的SP
低地址 |                            |

3. 返回顺序(先入后出):
   func2 返回 → 释放func2栈帧 ← 后入先出
   func1 返回 → 释放func1栈帧 ← 先入后出
   main 继续执行

当前图片展示的是:单个函数内部
展示了同一个函数的栈帧内部布局
局部变量 a和 b是同时分配、同时释放的
地址高低(a在低地址,b在高地址)只是它们在“内存公寓”中的房间位置
不同函数之间调用遵循:先入后出(LIFO)
当函数A调用函数B时,B的整个栈帧被“压入”栈顶
当函数B返回时,B的整个栈帧被“弹出”
这正是“先入后出”原则的体现

您的判断完全正确:
图片展示了局部变量在栈帧内的布局(房间内家具摆放)
不同函数调用遵循先入后出(套娃的套入和取出顺序)
这正体现了计算机系统的精巧设计:在宏观的函数调用层面使用栈的LIFO特性管理调用关系,在微观的函数内部则使用连续内存高效存储数据。

posted @ 2026-01-19 14:44  sgggr  阅读(0)  评论(0)    收藏  举报