1.定义
函数调用约定,也称函数调用协议,是指在函数调用时,确定函数参数如何传递给被调用的函数,以及如何返回结果值给调用者的一系列规则。也就是函数的调用者与被调用者之间如何传参以及如何恢复栈平衡。
2.职责
- 规定了函数参数的压栈顺序,即有多个参数时,按照什么顺序进行压栈;
- 规定了由谁负责清理栈,即函数调用后,是调用函数还是被调用函数来把栈恢复成调用前的样子。
3.种类
函数调用约定有很多,本文简要讨论以下两种:
(说明:调用者caller,即调用函数;被调用者callee,即被调用函数)
__cdecl
- 调用者:
- 将函数参数从右向左压栈;
- 调用结束后,负责调整栈指针以清除栈中的参数。这意味着调用者需要手动管理栈中的内容,确保栈的前后状态是正确的。
- 被调用者:
- 读取栈中参数以执行函数功能;
- 功能执行完毕后将结果返回给调用者,不负责清理栈。
__stdcall
- 调用者:
- 同样将函数参数从右向左压栈;
- 与
__cdecl
不同,调用者不负责在调用结束后清理栈中的参数。
- 被调用者:
- 同样读取栈中参数以执行函数功能;
- 调用结束后,除了负责调整栈指针以清除栈中的参数外,还要清理栈中的参数,这意味着由被调用者来管理函数执行期间所使用的栈空间。
4.使用场景
__cdecl
由于其灵活性(调用者可以传递任意数量的参数,即使与函数声明不符也不会在编译时产生错误)而被C和C++编译器用作默认的函数调用约定。而__stdcall
则常用于Windows API等需要严格参数匹配和自动栈管理的场合,特别是在Windows API和需要跨编译器、跨平台兼容性的场合中。
参考资料:
chatgpt
标签:__,调用者,cdecl,函数调用,参数,栈中,stdcall From: https://www.cnblogs.com/hell0er/p/18105211