__cdecl相比__stdcall的优势
呼叫X86函数的时候有两种清理堆栈的方式,在扩展的C/C++里面分别用__cdecl和__stdcall在函数声明和定义里面表示。函数的参数是用压入堆栈的方式使得函数能够通过访问堆栈访问相应的参数。比如以下函数声明:
void foo(int num);
呼叫它的时候,计算机会使用以下汇编代码:
pushl %num
call foo
假定是32位的X86,完成call之后ebp会指向函数的起始区域,ebp+4是函数的返回位置,也就是在函数返回时候将会回到这个地址。ebp+8就是第一个参数,ebp+12就是第二个参数,依此类推。
这就有一个问题,参数会占用一定区域的内存,谁来在函数返回的时候清理它们?
有两个办法,第一个是c语言用的标准办法,由函数的呼叫者负责清理,这就是__cdecl。第二个办法,是pascal用的标准办法,由函数的被呼叫者负责清理,这就是__stdcall。翻译为汇编语言如下:
__cdecl方式:
pushl %num
call foo
add 4,esp
意思是把堆栈点寄存器向上移动4个字节,这样就抹去了那个参数。
而__stdcall方式没有add 4,esp这行代码。但是在foo函数里面返回的时候有这样一句
ret 4
意思是返回的时候将会把堆栈点寄存器向上加4。
好了,讨论玩这两种呼叫形式的异同,现在开始讨论它们的优劣。
__cdel相对__stdcall的第一个优势是,它很适合用于回调函数(CALLBACK)。试想一个按钮需要如下格式的回调函数
void foo(GtkWidget * button,gpointer data)
假如你只是想按下这个按钮就结束窗口们的消息循环,用__stdcall你必须老老实实写道
void __stdcall exitMainLoop(GtkWidget * button,gpointer data){
gtk_main_quit();
}
尽管这个函数不需要使用到button相关的信息,但是你必须老老实实把两个参数的类型写上去。这是因为函数的呼叫者不管三七二十一一律压入两个参数,然 后等着你的函数来清理堆栈,假如你写的函数签名不一致,将会损坏堆栈!比如你直接把gtk_main_quit的指针当做回调函数指针,那么由于 gtk_main_quit并不清理堆栈,就会导致8个字节(两个参数)的堆栈不可用!
嗯,用__cdecl会怎样呢?__cdecl的呼叫者会负责清理堆栈,所以它压进多少参数,他就会清理多少个参数。那么把gtk_main_quit用做回调函数是安全的。因此我们就不必写一堆上面的代码,直接把gtk_main_quit当做回调函数即可。
这就是__cdecl相对__stdcall的第一个优势:可以把参数列表较短而且对应参数类型相同的函数指针当做较长的函数指针使用。
现在我们开始讨论__stdcall节省空间还是__cdecl节省空间。微软使用__stdcall来定义Win32 API,因为理论上__stdcall比较节省空间。他是这样认为的:
__stdcall消耗的空间是
ret X(X是一个地址,在32位系统为4字节),这样就是1字节(ret)+4字节(地址)=5字节
然后__cdecl消耗的空间是
(被呼叫者)ret
(呼叫者)addl X,esp 这样就是(ret)1字节+addl esp(1字节)+X(4字节)=6字节
没错,这个理论从单一个函数来看,一点也不错。但是从一个程序的角度来看,__stdcall还会因为这一字节之差胜过__cdecl?
一个用C/C++写的程序,绝大多数函数是被动态调用的,只有一小部分程序是明文规定是在那里被调用。所谓动态调用就是函数指针交给某些系统来使用,有那 些系统来决定何时调用你的函数。这样子__stdcall的问题就来了,就是每一个自己写函数都至少带有一个ret X。假如你写千个万个__stdcall的函数,就会多千个万个ret X。相反__cdecl只会在系统的某处出现一个addl X,esp。所需写的动态调用函数越多,占得便宜越大!
更何况,现在用C/C++写的函数也许不止有一个返回点。那么__stdcall在每一个返回点都需要有ret X,其损耗的道理和上面说的一样。
这就是__cdecl的第二个优势,其实更加节省资源。
__cdecl相比__stdcall的优势相关推荐
- 为什么Netty这么火?与Mina相比有什么优势?
转载自 为什么Netty这么火?与Mina相比有什么优势? Netty是什么?为什么这么火? Netty是目前最流行的由JBOSS提供的一个Java开源框架NIO框架,Netty提供异步的.事件驱动的 ...
- 【转】调用约定__cdecl、__stdcall和__fastcall的区别
什么是调用约定 函数的调用约定,顾名思义就是对函数调用的一个约束和规定(规范),描述了函数参数是怎么传递和由谁清除堆栈的.它决定以下内容:(1)函数参数的压栈顺序,(2)由调用者还是被调用者把参数弹出 ...
- __cdecl、__stdcall、__fastcall 与 __pascal 浅析
X86调用约定 calling convention:https://www.cnblogs.com/shangdawei/p/3323252.html __cdecl.__stdcall.__fas ...
- java和易语言对比_国外流行排行榜编程语言和易语言相比较的优势和劣势
国外流行排行榜编程语言和易语言相比较的优势和劣势 适合对象:对于初学者或者没有接触过编程语言的朋友有巨大参考价值. 比较特点:以C语言和Java两门最流行也是最经典的外国编程语言来和易语言相比较, 比 ...
- 数据库双活和ALWAYSON相比的四大优势
数据库双活和ALWAYSON相比的四大优势: 1.容灾:ALWAYSON是一主一备,主的突然故障,备的能否切换?切换后数据是否丢失?这都会有 问题的.数据库双活是双活,任何一个节点突然 ...
- 华为畅享10s值得买吗_华为畅享10S怎么样?与同价位相比有何优势?
摘 要 大家买手机主要看的三大要素是:时尚的外观.一流的拍照和流畅的体验.对于当下的年轻人来说价格也是参考之一,而华为手机致力于打造千元精品手机来让年轻人更好的享受新 大家买手机主要看的三大要素是:时 ...
- Python编程与其他编程语言相比有何优势?
Python编程与其他编程语言相比有何优势? [导语]随着企业对Python开发人员的需求量不断地增长,学习Python的人数也越来越多.Python之所以近两年如此火爆,与它自身简单易学的特点是息息 ...
- CDN和双线机房相比有何优势
1.什么类型的网站最需要CDN? 适合目标客户覆盖全国范围的网站,不论是南方电信.还是北方网通用户.铁通用户,均要求能快速访问到客户网站,彻底解决电信.网通之间的互访瓶颈. 另外国外的网站,如果需要提 ...
- win10php测试,window_Win10对决Win8:测试表明两者相比没有性能优势,目前,要搞清楚Windows 10性能相 - phpStudy...
Win10对决Win8:测试表明两者相比没有性能优势 目前,要搞清楚Windows 10性能相当困难.要对这款计划于7月29日发布的操作系统进行测试并非易事,因为公众还不能安装RTM版本.微软一直没有 ...
最新文章
- Nature、Science的绘图新宠,博导人论文覆盖率高达78%...
- 趋势科技实习面试后感
- MFC消息响应函数OnPaint
- Objective-C Autorelease Pool 的实现原理[转]
- 小孩学python有意义吗-世界冠军教练告诉你:少儿编程这些坑,能不踩就别踩!...
- 什么样的数据集可以被分成两类?
- matlab生产计划问题,基于MATLAB的生产计划最优化系统设计
- 每日程序C语言31-auto的使用
- Linux上下载chronyd安装包,如何在Linux中安装和使用Chrony时间同步
- unity算法面试_Unity面试题汇总
- 数据:昨日BTC和ETH期货持仓均减少约三成,波动率创3月以来新高
- ios 系统提示框_二个消息:关于iOS12.2和iOS13 beta 1系统功能
- Android学习(五)—— Android初级控件
- 多多参谋:拼多多推广怎么出价?该怎么做好推广?
- 秒杀竞拍屡创网络神话:馅饼还是美丽陷阱
- AX210 PCIE网卡 安装记录(linux)
- 关于maxIdle ,MaxActive,maxWait介绍
- 羊皮卷之五:假如今天是我生命中的最后一天
- 计算机组成原理——微程序控制器
- latex调整毕业论文目录中章节之间的间距
热门文章
- 香港惊现“人才荒”!IT毕业生就业率近100%,起薪超2.3W!
- bootstrap 按钮样式汇总
- QT学习笔记—QMovie播放GIF文件
- 从excel提取指定两列数据进行四参数曲线拟合,并输出拟合方程
- 【Python】Python的单双引号
- autocad.net(c#)获取autocad模型空间窗口大小
- c语言求素数500-1999,初等数论练习题
- 2019.7.2【PMP项目管理er日报】
- 百度云管家下载速度也作假
- 计算机应用生物,计算机应用生物信息学作业(10页)-原创力文档