代码之家  ›  专栏  ›  技术社区  ›  smwikipedia

关于呼叫约定的问题

  •  1
  • smwikipedia  · 技术社区  · 14 年前

    我记得很久以前,当我使用turbo C时,我不需要关心函数的调用约定,我使用或定义的每个函数的形式都是 C 呼叫约定。

    但是在我转到Windows平台之后,我发现有很多调用约定的规范,比如:

    winapi,stdcall,uu cdecl…

    这是编译器进化的结果吗?

    5 回复  |  直到 10 年前
        1
  •  6
  •   Yann Ramin    14 年前

    不,这只是Windows API的历史遗留问题。Windows之外的大多数系统通常不使用不同的调用约定(例外:系统调用和内核模式)。

        2
  •  5
  •   vanza    14 年前

    不同的调用约定具有不同的特性,有时使用的语言或API可能需要不同的特性。检查 this 本文概述了不同的调用约定,以及API通常使用它们的内容。

        3
  •  1
  •   Alexander Rafferty    14 年前

    winapi、stdcall等…不是调用约定,而是定义调用约定的宏。实际上,只有两到三种类型。宏的原因是具有向后兼容性。

        4
  •  0
  •   R.. GitHub STOP HELPING ICE    14 年前

    不,这是微软白痴的结果。没有理由在C环境中使用/混合不同的调用约定。

        5
  •  0
  •   BenMorel Manish Pradhan    10 年前

    打电话给约定很重要,但你自己必须考虑一下。

    当目标是用其他语言(如Pascal等)编写的其他操作系统或对象\库时,它变得相关。

    它确定在堆栈上(由调用方)推送哪些参数以及如何推送这些参数,以及当被调用函数返回时,谁负责从堆栈中弹出这些参数。

    因为C+C++支持可变参数列表,所以调用方的任务是弹出堆栈(因为被叫方不知道有多少参数给它)。

    因此,这会导致生成大量代码(每个函数调用都用堆栈pop代码进行扩展)。

    然而,对于不允许变量参数列表本地使用的语言,可以通过取消被调用函数来弹出堆栈themsel(它们总是知道如何调用它)。 这只会导致一段堆栈弹出代码(在被调用方的末尾),从而导致生成的代码更少。

    此外,语言还可以选择将参数推送到堆栈的方式。 它可以选择按在调用中写入的相同顺序推送参数(第一个参数优先,最后一个参数最后一个) 或者它可以选择先推最后一个参数,最后一个参数最后(如C+C++)。 后者允许“轻松”实现变量参数列表。

    如果不使用变量参数列表,则可以选择其他默认调用约定(如pascal)。 但是,这意味着没有指定调用约定的每个函数都将使用您选择的约定进行处理。 如果声明与它们的实现不同,您可能会得到未解决的外部错误(最多)、严重的运行时错误或(最多)错误的计算。

    作为一个实际例子: 我在一家移动电脑制造商做程序员。 他们使用一个特殊的(有限的)编译器来生成紧凑的代码(移动计算机的内存非常有限),因为MSVC生成了大型对象。

    我建议将C-Calling约定改为Pascal Calling约定和其他一些小改动。 从那时起,他们可以使用更复杂的编译器(msvc)并做更多的工作。