函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
原作:葡萄架上的牵牛花
原地址: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的线程函数地址
|
两者的参数传递顺序都是从右向左。
当你LoadLibrary一个DLL文件后, 把GetProcAddress取得的函数地址传给上面三个线程生成函数时,请务必确认实际定义在DLL文件的输出函数符合调用规范要求。否则,编译成Release版后运行,可能会破坏堆栈,程序行为不可预测。
VC中的相关编译开关:/Gd /Gr /Gz。另外,VC6中新增加的 /GZ 编译开关可以帮你检查堆栈问题。
我也是初学者,若有不对的地方、可以补充的地方,请指教。谢谢。
|
(补充)汇编语言视点的比较文章:Intel x86 Function-call Conventions - Assembly View
分享到:
相关推荐
函数的调用规则(__cdecl,__stdcall,__fastcall,__pascal) 关于函数的调用规则(调用约定),大多数时候是不需要了解的,但是如果需要跨语言的编程,比如VC写的dll要delphi调用,则需要了解。 microsoft的vc默认的是...
关于函数调用方式__stdcall和__cdecl详解 __stdcall __cdecl 两者的相同点与不同点 实例 __stdcall __stdcall的全称是standard call。是C++的标准调用方式。 函数参数的入栈顺序为从右到左入栈。函数返回时使用retn ...
Visual C/C++的编译器提供了几种函数调用约定,了解这些函数调用约定的含义及它们...__stdcall 被调用函数 右à 左 _函数名@数字 __fastcall 被调用函数 右à 左 @函数名@数字 thiscall(非关键字) 被调用函数 右à 左 /
_stdcall、_cdecl和_fastcall 的区别.zip
解决error LNK2001 无法解析的外部符号 int __cdecl sprintf
易语言cdecl回调处理源码,cdecl回调处理,stdcall_to_cdecl,stdcall_to_cdecl_free,回调函数,test,VirtualAlloc,VirtualFree,set_data
解决error LNK2005 void __cdecl operator delete(void
__stdcall_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后由被调用者负责清除栈的内容,Windows API 所采用的函数调用规则则是这种规则 ...
cdecl函数调用,了解printf这样的函数调用,对比stdcall会更清楚.zip
_cdecl、_stdcall、_fastcall和_thiscall整理
windows系统调用函数的方法有3种:__stdcall , __cdecl ,PASCAL 前两种是从右向左传递参数,最后一种是从左向右传递参数. __stdcall是windows系统调用API的标准方式 __cdecl是ANSI-C的标准调用方式
包含 Java 通过 RXTXComm 读写串口数据需要的动态链接库:SuperComSCL2008.Dll、rxtxSerial.dll、rxtxParallel.dll 和操作 SCL2008 显示屏的动态链接库 SCL_API_stdcall.dll、SCL_API_cdecl.dll
vb6.0 __stdcall函数内调用__cdecl函数
说明了 stdcall 与 cdecl 的区别
C++调用C函数实例详解 前言:以前见到extern “C”这样的语句,只是简单地知道跟外部链接有关,但是没有深刻理解它的意思。 首先,为什么要使用extern “C”修饰符? C++调用其它语言的函数,由于编译器生成函数的...
1>save-image-D435.obj : error LNK2001: 无法解析的外部符号 “private: char * __cdecl cv::String::allocate(unsigned __int64)” (?allocate@String@cv@@AEAAPEAD_K@Z) 1>save-image-D435.obj : error LNK2001: ...
stdcall cdecl 函数调用方式详解