C++函数参数的入栈顺序 |
您所在的位置:网站首页 › c语言中计算是从右往左 › C++函数参数的入栈顺序 |
长期以来大家都有一个疑问,C++函数参数的入栈顺序倒底是怎样的呢? 经验丰富的程序员一定会说C++参数的传输顺序是从右到左的, 这一点大家不妨可以自己建立一个控制台程序,看看函数入参的栈地址,你会发现栈底是最右边的参数,栈顶是最左边的参数, 事实胜于雄辩? 是的,从以上的事实来说经验是正确的. 但是同样也是错误的,这就跟我们说一个不带度量单位的数字一样,任何对的事情都是有限定条件的. 这里大家看到的实际上只是C++编译器默认的配置,实际上是怎样的呢? 实际上默认情况下C++使用__cdecl模式,因此是从右到左的传参顺序. 答案MS都写在了MSDN里,如下:
Argument Passing and Naming Conventions 参数传递和命名约定
如下表所示:
Keyword Stack cleanup Parameter passing __cdecl Caller Pushes parameters on the stack, in reverse order (right to left) //从右到左,默认工程都使用的这个选项 __clrcall n/a Load parameters onto CLR expression stack in order (left to right). //这里有个例外 __stdcall Callee Pushes parameters on the stack, in reverse order (right to left) __fastcall Callee Stored in registers, then pushed on stack __thiscall Callee Pushed on stack; this pointer stored in ECX
Note: The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype. 这里是一个注意事项,在用__stdcall调用时,如果是变长,编译器会自动修改为__cdecl.
但这里还有个问题,为什么采用从右到左的参数方式,而不使用从左到右的传参方式呢? 是的,这个问题很好,其实主要原因就在于变长参数. 一般我们命名一个变长函数时都类似于int display(int i, ...);这种格式, 注意参数都是用压栈方式实现的, 这里我用反证法来举证, 假如使用从左到右的传参方式,栈顶看到的是最后一个参数,那么我怎样知道首参数是哪一个呢? 因此要想知道首参数的值,则必须要知道参数的长度.而栈里并不知道这个长度,那么就无法通过指针偏移的方式找到首参数. 如果使用从右到左的传参方式,栈顶看到的就是左边输入的首参数,因此,无论怎样的变长,都可以通过指针偏移的方式找到值. 这个就是从右到左传参的奥秘! 不知道各位弄明白没有?
附录: #include "stdafx.h" #include #include int display(int i, ...); int _tmain(int argc, _TCHAR* argv[]) { display(1,2,3,4,5); return 0; } int display(int i, ...) { va_list argptr; va_start(argptr, i); int n = i; while (1) { printf( "%d\n", n ); n = va_arg( argptr, int ); if ((n < 0) || (n > 100000)) { break; } } va_end(argptr); return 0; }
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |