C语言深层次的修炼——函数栈帧的创建与销毁

在这里插入图片描述

栈帧是什么

不知大家接触过 “栈帧” 这个词没有,我第一次听以为是函数战争,心里怎么想也想不明白,战争(栈帧)是什么鬼????
然后我理解后才明白 栈(Stack)简单说, 是由于函数运行而临时占用的内存区域。而帧是函数开辟的会为它在栈上建立一个帧(frame)
我们了解后,那栈帧有什么用呢?
其实我们在学习C语言的时候会用很多的疑问,比如:
1.main函数肯定是要被调用的,那是被谁调用的呢?
2.函数里面的局部变量是怎么创建的?
3.局部变量又为什么是默认是随机值?而全局变量默认却是0?
4.函数是怎么传递参数的?参数的顺序又是怎么样的?
5.函数调用详细过程是怎么样的?调用后是怎么返回的?
让我们带着上面的疑问来一步步刨析吧。

大概轮廓

既然用到了函数,那我们就写一个简单的加法函数来看看过程是怎么样的吧。代码如下:

#include <stdio.h>
int Add(int x,int y)
{
	int z=0;
	z=x+y;
	return z;
}
int main()
{
	int a=2;
	int b=3;
	int c=0;
	c=Add(a,b);
	printf("%d ",c);
	return 0;
}

先说明一下我平常用的环境是vs2019,但是vs2019封装细节太多了,不容易看到整个汇编过程,所以这里我用的是 vs2010版本,由于环境不同,下面讲解的一些细节方面略有差异,但大体逻辑是不变的。
我们先来回答第一个问题,main函数是被谁调用的,
在这里插入图片描述
在这里插入图片描述

当调试的光标移动到这里,我们按F11返回调用main函数的函数,发现了调用main函数的是 __tmainCRTStartup函数 而这个函数又是被 mainCRTStartup函数调用的。
而函数是在栈上是靠寄存器 esp(栈顶指针)和ebp(栈底指针)来维护的,并且在栈区是是先使用高地址再使用底地址的,图片分析如下:
在这里插入图片描述
这就是main函数和Add函数在栈区上的大概轮廓,下面再让我们带着问题刨析main函数的具体创建过程。

函数创建过程

先让我们看看main函数的汇编是怎么样的?
在这里插入图片描述
调试到汇编:
在这里插入图片描述

接下来就是一步步的分析了,话不多说上图:
在这里插入图片描述
所以就解释了函数里面局部变量的创建过程,以及为什么局部变量会是随机值。
当main函数创建好变量后就要开始调用Add函数了,我们再分析又是怎么调用的
图片如下:
在这里插入图片描述

总之函数的创建是一步步的压栈过程,已经ebp 和esp 指针的变化过程。
所以函数的传参过程是先从后面开始时传的,先拷贝b再拷贝a,
形参存放在实参的那个函数当中的。
并且函数的形参只是实参的一份临时拷贝,改变形参不会影响实参。

函数销毁过程

函数创建执行相对于的功能后要销毁的,那是怎么样销毁呢?
其实函数的栈帧是靠esp 和ebp 指针来维护的,我们只要把ebp 赋值给 esp那么esp 和原来压进来的ebp 又维护能上一层的函数了。分析图片如下:

在这里插入图片描述

好了,分析到这里整个函数的过程就大概就是这样了,大家对开始的问题是不是已经有答案了呢?欢迎大家在评论区补充和留言。
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值