栈与调用惯例
来源:互联网 发布:java ssh框架教程 pdf 编辑:程序博客网 时间:2024/06/16 04:40
调用惯例
在讲调用惯例之前我们先说明一个问题。通过上一篇栈与栈帧的文章,我们可以发现一个现象:函数的调用者和被调用者对函数如何调用有着统一的理解。例如,它们双方都一致地认同函数的参数是按照某个固定的方式入栈,否则函数将无法正确运行。
例如1,函数:
int foo(int a,int b)
{
int n = 0;
````````````
}
如果函数的调用者在传递参数时先压入参数a,再压入参数b,而foo函数却认为其调用者先压入b再压入a,那么不难理解foo内部的a和b的值将会被调换。这样必然很引起很多问题导致程序无法正确执行。
例如2,调用参数传递途径:
如果函数的调用者是使用寄存器传递参数,而函数本身却认为是以参数通过栈传递,这样显然函数无法得到正确的参数。
既然函数调用会出现例子所描述的问题,但是我们平时写程序都能够正常运行,这就是因为存在一个调用惯例的约定。
调用惯例:函数的调用者与被调用者对于函数如何调用须要有一个明确的约定,只有双方都遵循同样的约定,函数才能被正确地调用。这样的约定成为调用惯例。
调用惯例一般约定的内容如下:
1、函数参数的传递顺序和方式
函数的调用方式有使用寄存器传递和通过栈传递之分。为了提高参数传递性能可以使用寄存器传递方式,但是参数传递最常见的是通过栈传递。对于一个参数的时候比较容易理解,只是对参数简单的压栈和出栈。但是如果是两个参数以上的时候,调用惯例必须规定函数调用者将参数压栈的顺序,分为从左只右还是从右到左。
2、栈的维护方式
函数将参数压入栈之后,函数体会被调用,函数执行完之后需要将压入栈的参数全部弹出以使得栈在函数调用前后保持一致。这个弹出的工作可以由函数的调用者来完成,也可以由函数本身来完成。
3、名字修饰策略
为了链接是对调用惯例进行区分,调用管理需要对函数本身的名字进行修饰。因为不同的调用惯例有不同的函数名字修饰策略。在C语言里面有多个调用惯例而默认的调用惯例是cdecl。在没有任何指定调用惯例的函数都是默认cdecl惯例。对于上例的函数foo的声明的完整形式为:int _cdecl foo(int a,int b)。
cdecl这个调用惯例是C语言默认的调用惯例,内容如下:
参数传递:从右到左的顺序压入参数进栈,例如上例子先压b再压a。
栈的维护方式:函数调用者来完成
名字修饰:直接在函数名称前加一个下划线,例如上例子的函数foo被修饰后变成_foo。
另外还介绍其他三种调用惯例,如下图:
- 栈与调用惯例
- 栈与调用惯例
- 栈与函数调用惯例
- 【Linux学习笔记】栈与函数调用惯例—上篇
- 【Linux学习笔记】栈与函数调用惯例—下篇
- 【Linux学习笔记】栈与函数调用惯例
- 调用惯例
- 【Linux学习笔记】栈与函数调用惯例 http://blog.csdn.net/xiaogugood/article/details/38490663
- 调用Register,Stdcall惯例
- 函数调用惯例
- 函数的调用惯例
- 函数的调用惯例
- 调用惯例的历史
- 寄存器的使用惯例和调用过程的栈
- VC++中的函数调用惯例
- VC++中的函数调用惯例
- VC++中的函数调用惯例
- 惯例
- Kinect for Windows SDK v2.0 开发笔记 (三)深度帧与红外帧获取
- 从一道面试题谈linux下fork的运行机制
- 关于hibernate一级,二级缓存以及事务隔离机制。
- 利用dfs解决规定路程问题
- 奇:取奇数行 20140721 ①文本处理
- 栈与调用惯例
- [leetcode] Binary Tree Zigzag Level Order Traversal
- 网易有道笔试(2008)
- ubuntu 自动生成 makefile
- POJ 1703 Find them, Catch them 二分图 并查集
- ubuntu下eclipse 运行c/c++ 程序出现not found binary解决
- 【hiho一下第三周】KMP计算模式串在原串出现次数
- struts2核心工作流程与原理
- 浅谈Struts2拦截器的原理与实现