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

Nli*_*tis 3 c function function-prototypes

我正在从K&R学习C,并在本书的第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");
}
Run Code Online (Sandbox Code Playgroud)

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

我与上面的代码的问题是,在Arch Linux的虚拟机,我的工作与GCC version 4.7.1上述文件可以编译并提供了以下错误:conflicting types for second.

然而,当相同的代码运行到我的物理机器,运行UCCntu 12.04GCC版本4.6.3,它编译就好了.

我的问题是:这是一个编译器功能吗?因为如果不是这样的话,我很惊讶它会编译,因为没有函数原型second,main(如果我已经正确理解)应该不能知道它second的存在.

cdh*_*wie 5

发生"冲突类型"错误消息是因为大多数C编译器在遇到尚未声明的函数时,将隐式声明该函数返回int的原型.所以当second()遇到它时main(),GCC 4.7.1推断出以下定义:

int second();
Run Code Online (Sandbox Code Playgroud)

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

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

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