程序小白
认证:优质创作者
所在专题目录 查看专题
不一样的宏定义(C语言小知识)
函数的调用和回调(OS小知识)
C语言指针数组(C语言小知识)
C语言中函数调用与堆栈详解
被C标准和编译器选项给狠狠的上了一课
extern "C" 的意义?——盘一下GCC!
作者动态 更多
电子元器件那些事儿:三极管工作区的判断如此简单①
1星期前
RT-Thread驱动之路:stm32设备驱动开发之SPI原理①
2星期前
RT-Thread驱动之路:stm32设备驱动开发之浅析注册机制⑤
2星期前
RT-Thread驱动之路:stm32设备驱动开发之uart中断处理④
3星期前
电子元器件那些事儿:继电器电路驱动设计②
3星期前

C语言中函数调用与堆栈详解

    

      为什么要了解C语言中函数调用与堆栈的关系?因为在操作系统中,所有的上下文切换,其实就是都是关于系统栈和线程栈之间的数据交换,,要真正的理解栈,只有放在应用中去看待它,函数的调用是栈最重要的应用,其实函数还有个秘密,那就是它其实就是自成一界的上下文,是不是很神奇。

【堆栈篇】

栈也叫堆栈、他就是一种数据结构,以先入后出的方式进行数据的存储。

      在C语言中栈是非常重要的,以STM32为例,虽然芯片只能执行机器指令,并且所有的语言都会被编译成机器指令,但是不同语言编译成机器指令的方式是不一样的,也就是说芯片是有运行环境的,芯片的启动都是从启动文件开始的,也就是所谓的startup.s ,这个时候,他是在汇编环境中执行的,然后他要切换到C语言环境,有一个最重要的事情,就是设置具体的堆栈结构。

      然后你就可以执行应用C语言编写的代码了,那么堆栈的作用到底是什么?

      答案就是:为了完成函数的调用,栈主要用来存放函数参数、局部变量、返回值等等数据。

      如何来维护一个栈内的数据,是通过堆栈指针来实现的,主要涉及的esp栈顶指针、ebp栈底指针

      栈顶指针主要用来完成数据的进栈和出栈操作。

      栈底指针主要用来查找当前栈内数据的位置,作为基地址参考。

【函数调用篇】

要完成一个函数的调用,CPU需要做些什么?

1.保存案发现场记录。

2.给要调用的函数创建一块空间,用于该函数执行过程所产生的记录。

3.函数调用执行完成,返回到原有记录。

简单的理解,函数调用就是需要保存一些相关的记录,而这些记录就被存在堆栈中。具体看看这个记录里面都有哪些内容(按顺序记录):

1.实际参数、返回地址、edp栈底指针首先入栈。

2.局部变量、形式参数、返回值入栈。

3.CPU运行相关的寄存器进栈。

关于函数调用入栈惯例

这里不具体介绍,有很多的标准,

主要用于规定例如参数是自左至右入栈,还是自右至左入栈?等等。

感兴趣可以问问度娘,看看都有哪些标准。

深入解析函数进栈(出栈刚好相反过程)。

让我用一段最简单的代码来说明关于函数调用而引发的堆栈操作

void MyCall(int a, int b)
{
	int p =11, q = 22;
}
int main(void)
{
	
	Mycall(33, 44);
	
	return 0;
}

跟着PC指针的位置来看一下堆栈在每一个时刻都是什么样子,

未执行调用函数时,如下:

执行Mycall函数入口,如下:

执行函数函数体时栈记录内容,如下:

关于堆栈的内容,其实还有溢出这一部分,太深了,太绕了,讲不明白。。。

能力有限,留到以后慢慢研究吧。

关于栈溢出部分还是多多少少的提及一下,在我们的程序运行进入C语言环境之前,栈的大小就要被定义好,也就是栈的容量是有限的和固定的。

函数的调用会消耗栈内存,函数的调用结束则会释放占内存,在我们实际应用过程中,最大的潜在问题是函数的嵌套调用,因为他只会进行压栈操作,不会弹栈操作,所以会导致栈内存不断被消耗,栈的内存又是有限的,当超过最大的限度时候,就会发生栈溢出错误,程序可能异常退出或者死机等现象。

这时候可能就会有我们老工程师经常给我们提的建议,函数嵌套不要太深,一般不要超过多少层,函数的内部尽量不要用大的局部变量。

当然我们也会想,那如果我们把栈定义的大点是不是就不用担心栈溢出了?

但是你要知道栈定义消耗的是RAM的空间。

而你的单片机又有多少的RAM空间呢?

一般也就几十KB吧

总要给应用程序留一点空间去申请来完成程序功能啊,所以建议栈定义不要太大,给一个特定的大小就可以,剩下的就是想办法减少函数嵌套的层数了。

关于栈的使用在PC机上又会出现其它的问题。

比如栈溢出攻击。。。超纲了,有兴趣的同学可以自行百度。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 6
收藏 4
关注 135
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧