1 函数调用默认采用__cdecl方式,可以省略

  1. **__cdeclC/C++和MFC程序默认使用的调用约定**,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且**由调用函数者把参数弹出栈以清理堆栈**。因此,实现可变参数的函数只能使用该调用约定。由于**每一个使用__cdecl约定的函数都要包含清理堆栈的代码**,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1114755/1610625191458-9ef4cfd4-71ea-4095-946d-e76232dd447c.png#align=left&display=inline&height=490&margin=%5Bobject%20Object%5D&name=image.png&originHeight=490&originWidth=1205&size=64129&status=done&style=none&width=1205)<br />**

2 __stdcall约定 用于 调用Win32 API函数

采用stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈stdcall可以写成_stdcall。好处是不用管堆栈平衡,因为会自动平衡。
只要你调用的时候和写dll的时候遵循的是同一种调用约定, 那么声明或者不声明为__stdcall其实是没有关系的。cdecl也照样可以正常调用。stdcall是习惯而已。某些特殊的函数,例如DllMain,DllGetClassObject,这类由系统调用的函数,因为系统是以stdcall方式进行调用的,所以必须用stdcall
image.png
image.png

3 __fastcall约定 用于 对性能要求非常高的场合

fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈fastcall可以写成_fastcall。
image.png
image.png

4 WINAPI一般用于修饰动态链接库中导出函数

define WINAPI __stdcall
可以使用WINAPI来为自己的API写一个有导出的API入口点的DLL。
消息处理函数就是这么定义的:
LONG WINAPI AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){}

5 CALLBACK仅用于修饰回调函数

define CALLBACK __stdcall
回调函数就是通过函数指针调用的函数。当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。
image.png
注:调用 与 回调
当一个程序调用windows API时的过程称为Call
当windows API调用程序里面的函数时这称之为Callback