c - C语言中的Pascal和cdecl关键字

标签 c cdecl

面试问题在我的脑海中引起了强烈的困惑,即让我们看看这个程序

#include "stdio.h"

int main()
{
    static int a=25;
    void cdecl conv1();
    void pascal conv2();
    conv1(a);
    conv2(a);
    return 0;
}

void cdecl conv1(int a,int b)
{
    printf("%d%d", a, b);
}

void pascal conv2(int a,int b)
{
    printf("\n%d%d", a, b);
}

输出为

25 0

0 25

但是为什么呢?又如何?

你能简单地向我解释一下吗,因为我不明白UGC书中提到的这个程序。

请帮助我更深入地理解这个概念,以便我更好地准备面试。

感谢您宝贵的时间。

最佳答案

(正如 Bo Persson 已经暗示的那样,这(可能)与所谓的调用约定有关。

维基百科上有一个很好的解释 x86 calling conventions .

简短摘要:不同的语言(分别是编译器)可能有不同的约定,函数参数的传递顺序(例如在堆栈上)。

如果您想要链接用不同语言编写代码的目标文件,这可能会成为一个问题。因此,一些编译器具有扩展来更改函数调用的调用约定。 (当然,如果没有任何指示使用 native 。)

<小时/>

Story Teller指出(除了调用约定问题之外)您的示例代码中还有其他一些内容非常可疑。

main 中的原型(prototype) conv1()conv2() 具有未指定的参数列表。这在 C 中是允许的(例如 SO: C: Unspecified number of parameters - void foo() 中详细说明)。不幸的是,它阻止了错误调用的检测。

conv1()conv2() 各有两个参数。但是,两者都在 main() 中使用 one 参数调用。这是未定义的行为。

(谢谢 Story Teller 让我认识到这一点。调用约定让我完全监督这一点以及 Bo Persson 评论中的提示。)

关于c - C语言中的Pascal和cdecl关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45434523/

相关文章:

c - 使用 C 我认为以多个零开头的文字被认为是八进制的吗?

c# - 为什么Cdecl调用在“标准” P/调用约定中经常不匹配?

c - 为什么我不应该使用 __fastcall 而不是标准的 __cdecl?

assembly - cdecl 调用约定

.net - 为什么在违反调用约定的情况下 PInvoke 不会崩溃(在 .NET 3.5 中)?

c - 如何使用 asm 获取指向输出缓冲区的指针?

c - 段错误,结构数组

c++ - EvtSubscribe 拉与推模型

c - 如何从用户程序中调用用内核模块编写的函数?

C - 从文件中读取特定行