我记得很久以前,当我使用Turbo C时,我不需要关心函数的调用约定,我使用或定义的每个函数都采用 C 调用的形式约定。
但是在我迁移到Windows平台之后,我发现有很多呼叫约定的指示符,例如:
WINAPI,STDCALL,__ cdecl ...
这是编译器发展的结果吗?
答案 0 :(得分:6)
不,它是Windows API的简单或大部分历史遗产。 Windows之外的大多数系统通常不使用不同的调用约定(例外:系统调用和内核模式)。
答案 1 :(得分:5)
不同的调用约定具有不同的特征,有时使用的语言或API可能需要不同的特性。查看this文章,了解不同调用约定的概述,以及通常使用它们的API。
答案 2 :(得分:1)
WINAPI,STDCALL,ect ......不是调用约定,它们是定义调用约定的宏。实际上,只有大约两三种实际类型。宏的原因是为了向后兼容。
答案 3 :(得分:0)
不,这是微软白痴的结果。在C环境中,不应该使用/混合不同的调用约定。
答案 4 :(得分:0)
召集会议非常重要,但你很少需要考虑。
在定位用其他语言(如pascal等)编写的其他操作系统或对象\库时,它变得相关。
它确定在堆栈上(由调用者)推送参数的内容和方式,以及当被调用函数返回时谁负责从堆栈中弹出这些参数。
由于C \ C ++支持变量参数列表,因此调用者的任务是弹出堆栈(因为被调用者不知道有多少参数被赋予它)。
因此,这会产生大量生成的代码(每个函数调用都使用stack-pop代码进行扩展)。
然而,本身不允许变量参数列表的语言可能会通过被调用的函数(他们总是知道它是如何被调用的)来释放堆栈。 这导致只有一个堆栈弹出代码(在被调用者的末尾),因此生成的代码较少。
更多的语言可以选择HOW参数被推送到堆栈的方式。 它可以选择按照它们在调用中写入的相同顺序推送参数(第一个参数,最后一个参数) 或者它可以选择先推送最后一个参数,然后将第一个参数推送到最后(如C \ C ++那样)。 后者允许“简单”实现变量参数列表。
如果不使用变量参数列表,则可以选择不同的默认调用约定(如PASCAL)。 但是,这意味着每个没有指定调用约定的函数都将使用您选择的约定来处理。 如果声明与它们的实现不同,您可能会得到未解决的外部错误(最多)或严重的运行时错误或(最坏的)错误计算。
作为一个实际例子: 我是一名移动计算机制造商的程序员。 他们使用特殊(有限)编译器生成紧凑代码(移动计算机的内存非常有限),因为MSVC生成了大型对象。
我建议将c调用约定更改为pascal调用约定和其他一些小的更改。 从那以后,他们可以使用更复杂的编译器(MSVC)并做更多的事情。