C语言中出现意外的函数原型行为

时间:2012-10-09 17:04:04

标签: c function function-prototypes

我正在学习K&K;当R表示范围规则时,R在本书的第4.4部分中感到困惑。在进一步讨论之前,让我发布我正在处理的源文件。

#include <stdio.h>

void first(void);

int main(void) {
    printf("In main.\n");

    first();
    second();

    return 0;
}

void first(void) {
    printf("In first.\n");
}

void second(void) {
    printf("In second.\n");
}

现在,除非我比我想象的更愚蠢,否则这本书给了我一个想法该函数原型(在与函数定义相同的文件中)存在的范围原因。也就是说,它们的存在是为了允许在编译文件的顶部声明函数,以便通知源文件的其余部分是否存在 “对象” 如果我可以提前打电话给它。

我对上述代码的问题是,在我正在使用GCC version 4.7.1的Arch Linux虚拟机中,上面的文件可以 NOT 编译并出现以下错误:{{1} }。

然而,当非常相同的代码运行到我的物理机器中时,使用 GCC版本4.6.3 运行 Ubuntu 12.04 它只编译细

我的问题是:这是一个编译器功能吗? 因为如果不是,我很惊讶它完全编译,因为没有函数原型{ {1}},conflicting types for second(如果我理解正确的话)应该无法了解second的存在。

1 个答案:

答案 0 :(得分:5)

出现“冲突类型”错误消息是因为大多数C编译器在遇到尚未声明的函数时会隐式声明该函数返回int的原型。因此,当second()中遇到main()时,GCC 4.7.1推断出以下定义:

int second();

然后,当编译器到达函数定义时,注意到推断的原型的签名与定义的签名不匹配,并以错误中止。

至于4.6.3成功编译此代码的原因,以下是猜测。 GCC 4.6.3可能有一些错误(或您决定使用的功能)允许函数实现与其原型的返回类型不同。由于C允许具有非void返回类型的函数在不返回任何内容的情况下终止(这使得它们的返回值未定义),这可能只是两个次优的事情相互抵消的情况。

(4.6.3中的行为也可能是版本之间默认编译器选项的更改,或者您可能正在使用不同的选项调用编译器。)