函数调用规范__cdecl和__stdcall的区别
来源:互联网 发布:长春淘宝图片拍摄 编辑:程序博客网 时间:2024/06/05 14:30
原作:葡萄架上的牵牛花
原地址:http://blog.bcchinese.net/happyjet/archive/2005/05/24/22545.aspx
__cdecl
__stdcall
C和C++程序的缺省调用规范
为了使用这种调用规范,需要你明确的加上__stdcall(或WINAPI)文字。即return-type__stdcallfunction-name[(argument-list)]
在被调用函数(Callee)返回后,由调用方(Caller)调整堆栈。
1. 调用方的函数调用
2. 被调用函数的执行
3. 被调用函数的结果返回
4. 调用方清除调整堆栈
在被调用函数(Callee)返回前,由被调用函数(Callee)调整堆栈。图示:
1. 调用方的函数调用
2. 被调用函数的执行
3. 被调用函数清除调整堆栈
4. 被调用函数的结果返回
因为每个调用的地方都需要生成一段调整堆栈的代码,所以最后生成的文件较大。
因为调整堆栈的代码只存在在一个地方(被调用函数的代码内),所以最后生成的文件较小。
函数的参数个数可变(就像printf函数一样),因为只有调用者才知道它传给被调用函数几个参数,才能在调用结束时适当地调整堆栈。
函数的参数个数不能是可变的。
对于定义在C程序文件中的输出函数,函数名会保持原样,不会被修饰。
对于定义在C++程序文件中的输出函数,函数名会被修饰,MSDN说Underscore character (_) is prefixed to names.我实际测试(VC4和VC6)下来发现好像不是那么简单。
可通过在前面加上extern“C”以去除函数名修饰。也可通过.def文件去除函数名修饰。
不论是C程序文件中的输出函数还是C++程序文件中的输出函数,函数名都会被修饰。
对于定义在C程序文件中的输出函数,An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list.
对于定义在C++程序文件中的输出函数,好像更复杂,和__cdecl的情况类似。
好像只能通过.def文件去除函数名修饰。
_beginthread需要__cdecl的线程函数地址
_beginthreadex和CreateThread需要__stdcall的线程函数地址
两者的参数传递顺序都是从右向左。
为了让VB可以调用,需要用__stdcall调用规范来定义C/C++函数。请参看Microsoft KB153586 文章:How To Call C Functions That Use the _cdecl Calling Convention。
当你LoadLibrary一个DLL文件后, 把GetProcAddress取得的函数地址传给上面三个线程生成函数时,请务必确认实际定义在DLL文件的输出函数符合调用规范要求。否则,编译成Release版后运行,可能会破坏堆栈,程序行为不可预测。
VC中的相关编译开关:/Gd /Gr /Gz。另外,VC6中新增加的 /GZ 编译开关可以帮你检查堆栈问题。
我也是初学者,若有不对的地方、可以补充的地方,请指教。谢谢。
阅读全文
0 0
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别一目了然
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别一目了然
- 函数调用规范__cdecl和__stdcall的区别
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)(转载)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
- react.js路由(4.x):模拟一个用户登录
- Vue兄弟组件之间的通信(EventBus)
- JavaWeb-Servlet编程 Part2
- 操作系统 --- 中断和轮询
- 钢铁行业,煤炭行业,有色金属行业的历史利润,负债率
- 函数调用规范__cdecl和__stdcall的区别
- Android使用jsoup解析音乐网站获取歌名与歌手名显示在ListView上
- SlidingMenu侧拉菜单,两侧都可以拉动
- React Native Picker (多列数据)
- BZOJ2242 SDOI2011 计算器
- Docker指定网桥和指定网桥IP
- P2327 [SCOI2005]扫雷
- PHP开源框架之AJAX
- Ubuntu14.04.3安装Openssh-server