在没有声明的情况下在另一个文件中调用函数不会产生编译

时间:2017-07-30 10:52:02

标签: c

//File a.c
void main()
{
    test();
}

//File b.c
#include<stdio.h>
void test()
{
    printf("Hi, I am test.");
}

我使用“gcc a.c b.c”编译此代码。然后我运行'a.out'并输出“你好我测试。”我的问题是在.c文件中没有test()的声明,为什么代码编译?

2 个答案:

答案 0 :(得分:2)

默认情况下,C中的函数为extern,这意味着即使没有a,链接器也能够将文件b中的函数连接到文件#include。或extern由程序员编写。

我的gcc使用此警告编译它:warning: implicit declaration of function...意思是,通过查看test();编译器猜测test是什么,并继续。如果您将test定义为失败的static,那么static将对抗默认extern

我认为您应该注意的一件事是implicit declaration也使编译器猜测返回类型为test,它会认为类型为{{1} }。这可能会导致问题。

答案 1 :(得分:1)

代码编译是因为C标准要求(至少在1999年之前)。在1999年的标准中删除了支持,尽管许多编译器仍然支持它 - 虽然它们可以被配置为在这种情况下警告(例如关于隐式声明)。

具体来说,出于向后兼容C89 / 90与预标准C的原因,代码调用函数的尝试隐式声明该函数返回int,并接受变量参数列表。

当编译器通过a.c

工作时会发生这种情况

链接时,它会起作用,因为该函数具有相同的名称。

如果调用函数的方式(返回值的使用和参数类型的数量)与函数的定义方式相匹配,这在实践中有效。如果没有匹配,则结果可能是未定义的行为。例如,如果函数使用4个参数定义并使用全部4,但调用者提供3,则行为未定义。同样,如果函数定义为返回double,但调用者假定它返回int

实际上,最好在调用之前声明所有编译单元中的所有函数(例如,通过包含标题)。这允许编译器检查调用函数的方式是否与其声明相匹配。

另请注意,在所有C标准中,main()都会返回int,而不是void。支持main()返回void是编译器扩展。