之前没有注意到的一些关键字,比如WINAPI,CALLBACK,原来是这个__stdcall的意思,而如果不声明__stdcall的话,就按默认的__cdecl处理,而这两者是不能相互转化的。
具体原因,看代码吧。
代码:
1 #include <windows.h> 2 #include <stdlib.h> 3 4 /** 5 * @author:zanzan101 6 */ 7 8 // 默认的情况,就是__cdecl类型的函数调用方式 9 void func() 10 { 11 printf("func "); 12 return; 13 } 14 15 void __cdecl func_cdecl() 16 { 17 printf("func_cdecl "); 18 return; 19 } 20 void __stdcall func_stdcall() 21 { 22 printf("func_stdcall "); 23 return; 24 } 25 void CALLBACK func_callback() 26 { 27 printf("func_callback "); 28 return; 29 } 30 void WINAPI func_winapi() 31 { 32 printf("func_winapi "); 33 return; 34 } 35 void PASCAL func_pascal() 36 { 37 printf("func_pascal "); 38 return; 39 } 40 class A 41 { 42 public: 43 void __cdecl do_something(){} 44 void __stdcall do_something_else(){} 45 void PASCAL do_something_else_else(){} 46 }; 47 48 // 默认的情况,就是__cdecl类型的函数调用方式 49 typedef void (*func_ptr)(); 50 51 // 也可以手动指明 52 typedef void (__cdecl *func_ptr_cdecl)(); 53 typedef void (__stdcall *func_ptr_stdcall)(); 54 55 int main() 56 { 57 58 // __cdecl 标准C函数调用方式,参数从右往左入栈,父函数负责清空栈 59 // __stdcall 标准C++函数调用方式,参数从右往左入栈,子函数负责清空栈,包括了CALLBACK和WINAPI(要引入<windows.h>) 60 // PASCAL PASCAL语言调用方式,参数从左往右入栈,子函数负责清空栈,但实际上。。。经查看发现,还是__stdcall???那__pascal呢??? 61 // __fastcall 可通过寄存器来传递参数 62 // thiscall 是一种概念,而非程序员可以指定的关键字,用类的成员函数的一种调用方式 63 64 65 // 正确方法: 66 func_ptr p1 = func; 67 p1(); 68 func_ptr_cdecl p2 = func_cdecl; 69 p2(); 70 p1 = p2; 71 p1(); 72 73 // 错误演示: 74 // error C2440: “初始化”: 无法从“void (__stdcall *)(void)”转换为“func_ptr” 75 // 两种调用方式不可转换 76 // func_ptr q = func_stdcall; 77 // q(); 78 79 // 正确方法: 80 func_ptr_stdcall q = func_stdcall; 81 q(); 82 q = func_callback; 83 q(); 84 q = func_winapi; 85 q(); 86 q = func_pascal; 87 q(); 88 system("pause"); 89 return 0; 90 }
输出结果:
func
func_cdecl
func_cdecl
func_stdcall
func_callback
func_winapi
func_pascal
请按任意键继续. . .