<C语言 入栈顺序>为什么函数入栈顺序从右往左?
2014-10-26 18:10
281 查看
最近在阅读《程序员的自我修养》,看到10.2节,又想起以前的入栈顺序,对此又深挖了一下:
大家都知道:
1.函数入栈顺序通常是:从右到左
2.从右到左的好处是,第一个参数就在栈顶,我们很方便就定位到了第一个参数的位置
3.网上一搜,大家都说,从右往左入栈的目的是方便的可变参数的使用,获得第一个参数的位置,
好的,大部分的讨论终结于此,那么,为什么我们要获得第一个参数的位置呢?为什么获得第一个参数就方便可变参数的使用和实现呢?
接下来,我们回想一下,可变参数的函数是如何使用的,不得不说到下面几个函数:
我们在使用可变参数的时候,一定会使用va_start这个函数,准确的说,它是一个宏:
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
也就是说,我们在使用可变参数的时候,必须要给出第一个参数,这样,va_start才能初始化后续的列表,而要定位第一个参数,直接用ebp-4即可(这里的减4是减去返回地址)
回答最初的问题:
1.为什么要获得第一个参数的位置:首先,C语言库使用可变参数函数时,就必须要求有第一个参数,获得第一个参数,可以定位后续的参数。这里又会想出一个问题,那么,为什么C语言库要至少有1个参数,我个人理解是,有一个参数可以方便用户处理后续的可变参数,因为如果你的代码中写死了后续参数的类型,你不如直接用固定参数,那么既然你使用了可变参数,就说明后续的类型个数,你可能是不确定的,你可以通过第一个参数来确定(当然,是否这样确定,如何确定由你的代码实现,参见printf的实现)
2.如果没有第一个参数,会怎样?我想了下,没有第一个参数,那么你整个参数的类型,是没法确定的(排除有的脑袋进水,能确定类型还是用可变参数的人),当然,要确定也不是没有办法,比如,你可以把参数类型写入一个配置文件中,读取,即配置文件实现了第一个参数的功能。那么基于此,还不如有一个固定的参数,让用户能够方便的获取可变参数的类型和个数。
3.基于1,2,可以知道为什么要有第一个参数,而不允许全部是可变参数?如果理解了1,2,既然C语言设计要求一定要有第一个参数,那么第一个参数就要方便获取,如果从右往左压栈,那么,第一个参数的地址直接ebp-4即可;如果从左往右压栈,由于可变参数的大小类型不知道,很难通过ebp去定位第一个参数的位置
大家都知道:
1.函数入栈顺序通常是:从右到左
2.从右到左的好处是,第一个参数就在栈顶,我们很方便就定位到了第一个参数的位置
3.网上一搜,大家都说,从右往左入栈的目的是方便的可变参数的使用,获得第一个参数的位置,
好的,大部分的讨论终结于此,那么,为什么我们要获得第一个参数的位置呢?为什么获得第一个参数就方便可变参数的使用和实现呢?
接下来,我们回想一下,可变参数的函数是如何使用的,不得不说到下面几个函数:
void va_start(va_list ap, last); type va_arg(va_list ap, type); void va_end(va_list ap); void va_copy(va_list dest, va_list src);
va_list是用于存放参数列表的数据结构。 va_start函数根据初始化last来初始化参数列表。 va_arg函数用于从参数列表中取出一个参数,参数类型由type指定。 va_copy函数用于复制参数列表。 va_end函数执行清理参数列表的工作。 引用自http://www.jb51.net/article/43192.htm
我们在使用可变参数的时候,一定会使用va_start这个函数,准确的说,它是一个宏:
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
也就是说,我们在使用可变参数的时候,必须要给出第一个参数,这样,va_start才能初始化后续的列表,而要定位第一个参数,直接用ebp-4即可(这里的减4是减去返回地址)
回答最初的问题:
1.为什么要获得第一个参数的位置:首先,C语言库使用可变参数函数时,就必须要求有第一个参数,获得第一个参数,可以定位后续的参数。这里又会想出一个问题,那么,为什么C语言库要至少有1个参数,我个人理解是,有一个参数可以方便用户处理后续的可变参数,因为如果你的代码中写死了后续参数的类型,你不如直接用固定参数,那么既然你使用了可变参数,就说明后续的类型个数,你可能是不确定的,你可以通过第一个参数来确定(当然,是否这样确定,如何确定由你的代码实现,参见printf的实现)
2.如果没有第一个参数,会怎样?我想了下,没有第一个参数,那么你整个参数的类型,是没法确定的(排除有的脑袋进水,能确定类型还是用可变参数的人),当然,要确定也不是没有办法,比如,你可以把参数类型写入一个配置文件中,读取,即配置文件实现了第一个参数的功能。那么基于此,还不如有一个固定的参数,让用户能够方便的获取可变参数的类型和个数。
3.基于1,2,可以知道为什么要有第一个参数,而不允许全部是可变参数?如果理解了1,2,既然C语言设计要求一定要有第一个参数,那么第一个参数就要方便获取,如果从右往左压栈,那么,第一个参数的地址直接ebp-4即可;如果从左往右压栈,由于可变参数的大小类型不知道,很难通过ebp去定位第一个参数的位置
相关文章推荐
- <转>C语言中的文件输入输出函数
- <<c++ primer>> 函数指针的笔记
- <二叉树 前中后 层序 非递归遍历 c语言实现>
- <数据结构>顺序栈的C语言实现
- <一>初探js特效魅力之函数传参03
- <数据结构>顺序列表的C语言实现
- <PY><core python programming笔记>C11 函数和函数式编程
- <python>Python的函数参数传递:传值?引用?
- <类模板 的 成员函数的特化>及<类 的 成员模板函数的特化>
- <细节>为什么构造函数不能是虚函数,为什么有虚析构函数
- <<通用的输入输出---------cout的扩展>> 引出的问题 ——扩展库函数功能
- <<C语言深度剖析>>学习之七之函数
- <<C语言深度剖析>>学习笔记之一:C语言中32个关键字
- <cctype> C字符函数
- <math.h>中的数学函数汇总
- C语言在中<math.h>中sqrt()函数的使用
- 为什么Oracle的伪列rownum不支持>,>=,=,between...and,而都用<
- <<c程序设计语言>>-4- 函数与程序结构
- <转>Class.forName的作用以及为什么要用它
- < Unity 3D专栏 >添加控件检测事件,函数处理