C++函数参数的入栈顺序

原创 2013年10月08日 19:28:20

长期以来大家都有一个疑问,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 <stdio.h>
#include <stdarg.h>

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;
}

 

C语言中函数参数的入栈顺序

C语言中函数参数的入栈顺序 http://www.cnblogs.com/xkfz007/archive/2012/03/27/...
  • u014181676
  • u014181676
  • 2014年03月25日 21:51
  • 1331

C语言函数参数压栈顺序为何是从右到左?

要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,…) 没错,它是一个不定参函数,那么我们在实际使用中是怎么样...
  • jiange_zh
  • jiange_zh
  • 2015年08月09日 23:19
  • 2478

C C++ Intro - C语言中函数参数入栈的顺序

C语言中函数参数入栈的顺序 先通过一个小程序来看一看: #include void foo(int x, int y, int z) { printf("x = %d a...
  • fanbird2008
  • fanbird2008
  • 2015年09月07日 18:00
  • 622

[C/C++]函数参数的入栈顺序与可变参数的实现

#include void foo(int x, int y, int z) {         printf("x = %d at [%X]\n", x, &x);         prin...
  • qq_21071767
  • qq_21071767
  • 2015年10月11日 13:55
  • 182

[C/C++]函数参数的入栈顺序与可变参数的实现

转载地址:http://blog.sina.com.cn/s/blog_54f82cc2010133mn.html #include void foo(int x, int y, int z) ...
  • wangxiaosu
  • wangxiaosu
  • 2012年11月06日 22:05
  • 1201

[C/C++]函数参数的入栈顺序与可变参数的实现

#include void foo(int x, int y, int z) {         printf("x = %d at [%X]\n", x, &x);         prin...
  • FrankieWang008
  • FrankieWang008
  • 2013年07月22日 10:03
  • 1311

c/c++函数参数的入栈顺序和计算顺序

先给出本文参考的链接: [C/C++函数参数读取顺序 ] [关于c语言和c++中的函数参数的执行顺序的问题],裘宗燕老师的讲解非常准确。尤其是对于表达式计算,表达式的副作用,都有启发性的讲解。 ...
  • Kang_TJU
  • Kang_TJU
  • 2017年06月15日 11:06
  • 222

C/C++函数参数的入栈顺序,计算顺序和可变参数的实现

函数参数入栈顺序,参数计算顺序以及可变参数的实现
  • sunbibei
  • sunbibei
  • 2015年10月15日 23:20
  • 925

C语言中函数参数的入栈顺序

对技术执着的人,比如说我,往往对一些问题,不仅想做到"知其然",还想做到"知其所以然".C语言可谓博大精深,即使我已经有多年的开发经验,可还是有许多问题不知其所以然。某天某地某人问我,C语言中函数参数...
  • FrankieWang008
  • FrankieWang008
  • 2012年04月20日 16:15
  • 3223

C语言中函数参数入栈的顺序

先通过一个小程序来看一看: #include void foo(int x, int y, int z) { printf("x = %d at [%X]n", x, &x);...
  • syflyhua
  • syflyhua
  • 2013年03月16日 15:28
  • 435
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++函数参数的入栈顺序
举报原因:
原因补充:

(最多只允许输入30个字)