调用约定__stdcall / __cdecl

__cdecl与__stdcall这两种调用约定之间的主要差别在于由谁来执行对参数的清理工作。
如果是__cdecl,那么主调函数将负责执行清理工作,如果是__stdcall那被调函数将负责执行清理。
通常,我们倾向于使用__stdcall,它能够减少生成代码的规模。因为不需要每次调用时,都在返回后对esp进行操作,比如add esp, 0Ch.(抵消三个参数的大小)
__cdecl存在的意义是?支持变长数量的参数。

调用约定 参数传递 栈的清理工作 函数名修饰
stdcall  右到左  被调函数  函数名字前加"_",并且在后面增加'@'以及栈空间所需要的字节数
cdecl  右到左  主调函数  在名字前加"_"
这种函数名的规范,在编译后,比如缺少lib文件时,会看到。

通常编译器和连接器将一起来确保根据调用约定调用正确的函数。但,有时连接器不能提供这种机制,此时必须小心避免不匹配的情况。

windows API一般都会有WINAPI的前缀,表示调用约定为__stdcall

#define WINAPI __stdcall

Win32的API函数都遵循__stdcall调用约定。

在VC++开发环境中,默认的编译选项是__cdecl(C调用约定),对于那些需要__stdcall调用约定的函数,在声明时必须显式地加上__stdcall。在Windows程序中,回调函数必须遵循__stdcall调用约定,所以我们在声明回调函数时要使用CALLBACK。

posted @ 2012-06-19 09:56  友学友  阅读(217)  评论(0编辑  收藏  举报