当前位置:网站首页>函数调用模型
函数调用模型
2022-06-21 16:03:00 【打酱油的;】
1.概念补充----宏函数
概念:
预编译做了宏替换
注意事项:
保存运算完整性(要注意符号结合)依旧要以原来优先级为先!!!!!

使用场景:
将短小的函数封装为宏函数 以空间换时间,在一定程度上会比普通函数效率高(普通函数会有入栈和出栈的时间开销)

2.函数调用流程
栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今能见到的所有计算机的语言。在解释为什么栈如此重要之前,我们先了解一下传统的栈的定义:
在经典的计算机科学中,栈被定义为一个特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将压入栈中的数据弹出(出栈,pop),但是栈容器必须遵循一条规则:先入栈的数据最后出栈(First In Last Out,FILO).
在经典的操作系统中,栈总是向下增长的。压栈的操作使得栈顶的地址减小,弹出操作使得栈顶地址增大。
栈在程序运行中具有极其重要的地位。最重要的,栈保存一个函数调用所需要维护的信息,这通常被称为堆栈帧(Stack Frame)或者活动记录(Activate Record).一个函数调用过程所需要的信息一般包括以下几个方面:
- 函数的返回地址;(用于函数调用完以后可以继续执行)
- 函数的参数;
- 局部变量;
- 保存的上下文:包括在函数调用前后需要保持不变的寄存器。临时变量
我们从下面的代码,分析以下函数的调用过程:
int func(int a,int b){ int t_a = a; int t_b = b; return t_a + t_b; } int main(){ int ret = 0; ret = func(10, 20); return EXIT_SUCCESS; } |

3.调用惯例
主调函数和被调函数要有一致约定,函数才能被调用起来,约定称为调用惯例
现在,我们大致了解了函数调用的过程,这期间有一个现象,那就是函数的调用者和被调用者对函数调用有着一致的理解,例如,它们双方都一致的认为函数的参数是按照某个固定的方式压入栈中。如果不这样的话,函数将无法正确运行。 如果函数调用方在传递参数的时候先压入a参数,再压入b参数,而被调用函数则认为先压入的是b,后压入的是a,那么被调用函数在使用a,b值时候,就会颠倒。 因此,函数的调用方和被调用方对于函数是如何调用的必须有一个明确的约定,只有双方都遵循同样的约定,函数才能够被正确的调用,这样的约定被称为”调用惯例(Calling Convention)”.一个调用惯例一般包含以下几个方面:
函数的传递有很多种方式,最常见的是通过栈传递。函数的调用方将参数压入栈中,函数自己再从栈中将参数取出。对于有多个参数的函数,调用惯例要规定函数调用方将参数压栈的顺序:从左向右,还是从右向左。有些调用惯例还允许使用寄存器传递参数,以提高性能。
主调或者被调 调用
在函数将参数压入栈中之后,函数体会被调用,此后需要将被压入栈中的参数全部弹出,以使得栈在函数调用前后保持一致。这个弹出的工作可以由函数的调用方来完成,也可以由函数本身来完成。 为了在链接的时候对调用惯例进行区分,调用惯例要对函数本身的名字进行修饰。不同的调用惯例有不同的名字修饰策略。 事实上,在c语言里,存在着多个调用惯例,而默认的是cdecl.任何一个没有显示指定调用惯例的函数都是默认是cdecl惯例。比如我们上面对于func函数的声明,它的完整写法应该是: int _cdecl func(int a,int b); 注意: _cdecl不是标准的关键字,在不同的编译器里可能有不同的写法,例如gcc里就不存在_cdecl这样的关键字,而是使用__attribute__((cdecl)). |
调用惯例 | 出栈方 | 参数传递 | 名字修饰 |
cdecl(默认) | 函数调用方式 如main调用函数 就是main | 从右至左参数入栈 | 下划线+函数名 |
stdcall | 函数本身 | 从右至左参数入栈 | 下划线+函数名[email protected]+参数字节数 |
fastcall | 函数本身 | 前两个参数由寄存器传递,其余参数通过堆栈传递。 | @+函数名[email protected]+参数的字节数 |
pascal | 函数本身 | 从左至右参数入栈 | 较为复杂,参见相关文档 |

4.函数变量传递分析





代码实例:

边栏推荐
- Many software companies are actually "jokes"
- Ares Ares I pledged LP mining crowdfunding model DAPP smart contract customization
- LeetCode 25:K个一组翻转链表
- Oracle JDBC Driver
- Three color mark removal method
- Come and watch – tpt18 new report
- 为什么要做茶叶商城小程序app开发?
- Research on symmetric TSP Based on MATLAB
- 【SQLite】解决unrecognized token:“‘“
- Alibaba cloud server + pagoda panel + no domain name deployment web project
猜你喜欢
![[observation] Microsoft's](/img/70/c598ef50a4c06f9bdcb7a935dbf62b.png)
[observation] Microsoft's "cloud + end" comprehensive innovation makes hybrid cloud simpler, more flexible and more secure

智能制造的下一站:云原生+边缘计算双轮驱动

使用PicGo-Core 和 阿里云 实现typora图片自动上传

Many software companies are actually "jokes"

Unittest framework

Design and implementation of face verification system for floating population management

Elegant request retry using guzzle Middleware

Postman基本操作

还在用 Xshell ?试试这款炫酷的 SSH 终端工具吧,功能很强大!

UDP和TCP的对比
随机推荐
【毕业N年系列】 毕业第四年
Overseas new things | zoovu, an American AI startup, raised a new round of financing of US $169million to optimize the online "product discovery" experience for consumers
Pytest框架
Google Earth engine (GEE) - sentinel-1 comprehensively check the difference between automatic landslide monitoring before and after two months (Guatemala as an example)
[SQLite] solve unrecognized token:“‘“
Qtcreator error reporting solution
使用PicGo-Core 和 阿里云 实现typora图片自动上传
gp中的decode函数实现
Comparison of UDP and TCP
rtmp webrtc 协议 openssl 等安装
[learn FPGA programming from scratch -38]: Advanced - syntax - functions and tasks
很多軟件公司,其實都是“笑話”
Template: p6114 [template] Lyndon Decomposition & runs (string)
快速排序简单思路及程序
进击的程序员,如何提升研发效能?|直播预告
[Error] ‘vector‘ was not declared in this scope
Research on symmetric TSP Based on MATLAB
tinymce.init()浏览器兼容问题
4. 构造【LR(1)分析表(包含构建项目规范族)】
Come and watch – tpt18 new report