c/c++的函数参数压栈顺序
整理日: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参数压栈是从左到右.
注意点
- 尽量不要在函数参数中运行象pop之类的参数
- 32bit和64bit同一源码时要注意
c/c++的函数参数压栈顺序的更多相关文章
- C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)
上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇 ...
- C/C++多参数函数参数的计算顺序与压栈顺序
一.前言 今天在看Thinking in C++这本书时,书中的一个例子引起了我的注意,具体是使用了下面这句 单看这条语句的语义会发现仅仅是使用一个简单的string的substr函数将所得子串pus ...
- c语言中函数参数入栈的顺序是什么?为什么
看到面试题C语言中函数参数的入栈顺序如何? 自己不知道,边上网找资料.下面是详细解释 #include <stdio.h> void foo(int x, int y, int z){ ...
- c++参数入栈顺序和参数计算顺序
关于 本文涉及到代码,演示环境为:win10 + VS2017 ,ubuntu+clang clang版本: 参数入栈顺序 顺序 几种常见的函数参数入栈顺序,还有两种就不介绍了(__clrcall._ ...
- 在实验中观察指针——C++ 函数参数的压栈顺序
前言 好久没写东西了,突发奇想,写写函数参数的压栈顺序 先看看这个问题 https://q.cnblogs.com/q/137133/ 然后看我简化的代码,猜输出结果是多少? #include< ...
- C语言函数入参压栈顺序为什么是从右向左?
看到有人提问到,在处理printf/cout时,压栈顺序是什么样的?大家都知道是从右往左,也就是说从右往左的计算,但是,这里的计算不等于输出. a++和++a的压栈的区别:在计算时,遇到a++会记录此 ...
- C、C++语言中参数的压栈顺序
要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,-) 没错,它是一个不定参函数,那么我们在实际使用中是怎么样知道它的参 ...
- 测试当前C环境的栈帧增长方向以及传递参数时的压栈顺序
前文链接:上次由于一个很常见的printf-bug(下文有提及)引发了我对栈的思考,并写下了一点总结.这次就尝试对不同的C环境进行实践,检测其传递参数的一些性质. 这是今天写的检查C环境的一段程序.能 ...
- C/C++---printf/cout 从右至左压栈顺序实例详解
__cdecl压栈顺序实例 明白计算:计算是从右到左计算的 栈和寄存器变量:x++,是将计算结果存放到栈空间,最后是要出栈的:而++x和x是将计算结果直接存放到某个寄存器变量中(是同一个),所以计算完 ...
随机推荐
- Android的配置界面PreferenceActivity
我想大家对于android的系统配置界面应该不会陌生吧,即便陌生,那么下面的界面应该似曾相识吧,假若还是不认识,那么也没有关系,我们这一节主要就是介绍并讲解android 中系统配置界面的使用,相信大 ...
- 【UML九种图系列】之用例图
用例图: 由参与者(Actor).用例(UseCase)以及它们之间的关系构成的用于描述系统功能的动态视图称为用例图.用例图描述了系统提供的一个功能单元.用例图的主要目的是帮助开发团队以一种图形化的方 ...
- [Eclipse]The type XXX cannot be resolved. It is indirectly referenced from required .class files
在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误 ...
- ASP.NET性能优化之分布式Session
如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session ...
- Java基础知识强化之网络编程笔记08:TCP之客户端键盘录入服务器控制台输出
1. 客户端: package cn.itcast_08; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...
- Eclipse - 添加 PyDev 插件
1. 安装PyDev插件 启用Eclipse.在Help菜单中,选择Install New Software···, 然后点击Add按钮.在Location中输入:http://pydev.org/u ...
- 简单地使用jquery的validate
简单地使用jquery的validate ——@梁WP 摘要:本文通过一个很简单的例子,讲解了jquery validate的最基础使用方式. 一.源代码 注意事项都写在代码的注释里了,哈哈. < ...
- spring参数类型异常输出,SpringMvc参数类型转换错误输出
spring参数类型异常输出, SpringMvc参数类型转换错误输出 >>>>>>>>>>>>>>>> ...
- 使用DataContractJsonSerializer类将类型实例序列化为JSON字符串和反序列化为实例对象 分类: JSON 前端 2014-11-10 10:20 97人阅读 评论(1) 收藏
一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大 ...
- WCF学习笔记一(概述)
WCF Windows Communication Foundation 分布式通信框架.WCF是对现有分布式通信技术的整合.是各种分布式计算的集大成者.主要整合技术如下图: WCF的服务不能孤立的 ...