整理日:2015年3月18日

为了这句话丢了很多次人.无所谓了,反正咱脸皮厚.

总结一下

编译出来的c/c++程序的参数压栈顺序只和编译器相关!

下面列举了一些常见的编译器的调用约定

VC6

调用约定 堆栈清除 参数传递
__cdecl 调用者 从右到左,通过堆栈传递
__stdcall 函数体 从右到左,通过堆栈传递
__fastcall 函数体 从右到左,优先使用寄存器(ECX,EDX),然后使用堆栈
thiscall 函数体 this指针默认通过ECX传递,其它参数从右到左入栈

__cdecl是CC++的默认调用约定; VC的调用约定中并没有thiscall这个关键字,它是类成员函数默认调用约定;

CC++中的main(或wmain)函数的调用约定必须是__cdecl,不允许更改;

默认调用约定一般能够通过编译器设置进行更改,如果你的代码依赖于调用约定,请明确指出需要使用的调用约定;

C++Builder6

调用约定 堆栈清除 参数传递
__cdecl 调用者 从右到左,通过堆栈传递(与CC++默认调用约定兼容)
__stdcall 函数体 从右到左,通过堆栈传递(与VC中的__stdcall兼容)
__fastcall 函数体 从左到右,优先使用寄存器(EAX,EDX,ECX),然后使用堆栈 (兼容Delphi的register)
msfastcall 函数体 从右到左,优先使用寄存器(ECX,EDX),然后使用堆栈(兼容VC的__fastcall)
__pascal 函数体 从左到右,通过堆栈传递

由于能力和资源有限,只能找到这些东西,主要的差异体现在fastcall上面,vc是前两个参数放入寄存器,后面的压栈,bcb是前3哥参数使用寄存器, 更有变态的,一个朋友朋友说有的参数超过7个以后前5个从左到右传递,后面的从右到走,上面说的不可不信,不可全信.

如何确定你的编译采用的那种顺序那?

#include <stdio.h>
int f(int i,int j,int k);
int main()
{
static int i=0;
f(i++,i++,i++);
return 0;
} int f(int i,int j,int k)
{
int l;
int g;
printf("k=%d:[%x] ",k,&k);
printf("j=%d:[%x] ",j,&j);
printf("i=%d:[%x] ",i,&i);
printf("\_\_\_\_\_\_\_\_\_\__ ");
printf("l:%x ",&l);
printf("g:%x ",&g);
}

看看k->i的地址的增长顺序和l->g的顺序是否相同,如果相同则是从右到左,否则从左到右.

PS

本来通过打印参数的值来判断那个先入栈,结果被一个朋友批评了,

他说:压栈顺序和参数计算顺序不是一回事,所以还是看地址更有保证.

看过的朋友当作笑谈吧。

曾经看到一篇文章上面说:c/c++参数压栈顺序是从右到左,pascal参数压栈是从左到右.

注意点

  1. 尽量不要在函数参数中运行象pop之类的参数
  2. 32bit和64bit同一源码时要注意

c/c++的函数参数压栈顺序的更多相关文章

  1. C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

    上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇 ...

  2. C/C++多参数函数参数的计算顺序与压栈顺序

    一.前言 今天在看Thinking in C++这本书时,书中的一个例子引起了我的注意,具体是使用了下面这句 单看这条语句的语义会发现仅仅是使用一个简单的string的substr函数将所得子串pus ...

  3. c语言中函数参数入栈的顺序是什么?为什么

    看到面试题C语言中函数参数的入栈顺序如何? 自己不知道,边上网找资料.下面是详细解释 #include <stdio.h> void foo(int x, int y, int z){   ...

  4. c++参数入栈顺序和参数计算顺序

    关于 本文涉及到代码,演示环境为:win10 + VS2017 ,ubuntu+clang clang版本: 参数入栈顺序 顺序 几种常见的函数参数入栈顺序,还有两种就不介绍了(__clrcall._ ...

  5. 在实验中观察指针——C++ 函数参数的压栈顺序

    前言 好久没写东西了,突发奇想,写写函数参数的压栈顺序 先看看这个问题 https://q.cnblogs.com/q/137133/ 然后看我简化的代码,猜输出结果是多少? #include< ...

  6. C语言函数入参压栈顺序为什么是从右向左?

    看到有人提问到,在处理printf/cout时,压栈顺序是什么样的?大家都知道是从右往左,也就是说从右往左的计算,但是,这里的计算不等于输出. a++和++a的压栈的区别:在计算时,遇到a++会记录此 ...

  7. C、C++语言中参数的压栈顺序

    要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,-) 没错,它是一个不定参函数,那么我们在实际使用中是怎么样知道它的参 ...

  8. 测试当前C环境的栈帧增长方向以及传递参数时的压栈顺序

    前文链接:上次由于一个很常见的printf-bug(下文有提及)引发了我对栈的思考,并写下了一点总结.这次就尝试对不同的C环境进行实践,检测其传递参数的一些性质. 这是今天写的检查C环境的一段程序.能 ...

  9. C/C++---printf/cout 从右至左压栈顺序实例详解

    __cdecl压栈顺序实例 明白计算:计算是从右到左计算的 栈和寄存器变量:x++,是将计算结果存放到栈空间,最后是要出栈的:而++x和x是将计算结果直接存放到某个寄存器变量中(是同一个),所以计算完 ...

随机推荐

  1. EasyUI-动态添加tab

    layout效果 代码: <%@ page language="java" contentType="text/html; charset=utf-8" ...

  2. MFC ListControl使用方法

    在原来博客中有:MF CListControl 简单功能使用 推荐文章:MFC类CtrlList用法 今天又又一次来介绍点新东西:双击击listcontrol  做出响应.当然你能够做的还有非常多,比 ...

  3. FastDFS 的部署、配置与测试的

    部署篇:http://soartju.iteye.com/blog/803477 配置篇:http://soartju.iteye.com/blog/803524 测试篇:http://soartju ...

  4. [Angular 2] DI in Angular 2 - 1

    Orgial aritial --> Link The problem with Angular 1 DI: Angular 2 DI: Solve the singletons problem ...

  5. 文件读写操作(含SDCard的读写)

    1.在AndroidManifest文件下添加SDCard的读写权限 <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name ...

  6. Java基础知识强化之网络编程笔记08:TCP之客户端键盘录入服务器控制台输出

    1. 客户端: package cn.itcast_08; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...

  7. 验证jquery.validate.js

    <pre>jquery.validate.js使用之自定义表单验证规则,下面列出了一些常用的验证法规则 jquery.validate.js演示查看 <a href="ht ...

  8. [功能帮助类] C#取汉字拼音的首字母PinYin帮助类 (转载)

    点击下载 PinYin.rar 主要功能就是取汉字拼音的首字母,只要你输入一个汉字,或者是多个汉字就会取出相应的道字母,主要是方便查询使用的 /// <summary> /// 编 码 人 ...

  9. 从腾讯QQ升级游戏之“快速加入游戏”功能的实现缺陷看C/S之间如何正确分配相关协作

    转载:http://space.itpub.net/17007506/viewspace-615570 笔者在闲暇时,偶尔会登录腾讯QQGame玩玩升级游戏.这确实是一款非常优秀的软件作品,腾讯的开发 ...

  10. javascript创建对象(二)

    原型模式:每创建一个函数都有一个prototype属性,它是一个指针,指向一个对象: 原型模式创建函数的方式: function Movie(){ }; Movie.prototype.name=&q ...