从历史上看,为什么似乎每个人和他们的弟弟都定义了自己的调用约定?你有 C、C++、Windows、Pascal、Fortran、Fastcall 以及可能还有无数其他我没有想到的语言。难道不应该有一种约定对于绝大多数用例来说是最有效的吗?是否有任何充分的理由选择其中一种而不是另一种?
您提到的调用约定是针对不同语言和不同硬件设计了数十年的。他们都有不同的目标。 cdecl 支持 printf 的变量参数。 stdcall 导致代码生成更小,但没有变量参数。在旧机器上,Fastcall 可以大大加快仅使用一两个参数的简单函数的性能(但现在很少有加速。)
请注意,当 x64 引入时,至少在 Windows 上,它被设计为具有单一调用约定。
Raymond Chen 撰写了有关调用约定历史的精彩系列文章,您可以从这里开始。
因为历史上每个人和他们的弟弟确实定义了自己的调用约定。它们都是为了不同的目的而创建的,因此受到不同的性能需求的驱动。例如,C++ 倾向于优化传递
this
参数。
部分原因是微处理器(或处理器)的底层架构。大多数语言都从特定的 CPU 开始,并与该架构有点纠缠在一起。例如,旧的 Univac 1100 系列计算机甚至没有调用堆栈!
另一部分原因是,在尝试了多种做事方法之前,不可能预见到最佳解决方案。
它们是为了不同的目的而创建的,并且具有不同的优化系统。
例如,为了减少“堆栈溢出”(没有双关语的意思),有些人想到了各种想法来调用函数以防止堆栈溢出。
另一个例子是 Lambda 演算。不要太含糊,但在 Lambda 中,函数只能传递一个参数并返回一个值,因此也需要自己的调用约定。