为什么可以调用稍后在C中声明的函数?

时间:2012-11-28 10:08:19

标签: c

我有这个小代码来演示它:

#include "stdio.h"

int main() {
    int a = testfunc();  // declared later
    printf("%d", a);
    return 0;
}

int testfunc() {
    return 1;
}

它没有错误地编译,并且按预期编译输出1

请参阅操作:http://ideone.com/WRF94E

为什么没有错误?它是C规范的一部分还是编译器相关的东西?

6 个答案:

答案 0 :(得分:5)

隐式声明函数testfunc()。编译器无法执行任何签名检查,因此您可能会遇到运行时错误,以防您无法以核心方式调用它。

这是C规范的一部分。但是C规范中的建议是在当前文件的开头或头文件中声明您计划实现和使用的所有函数。

答案 1 :(得分:2)

因为默认情况下编译器将未声明的函数视为

int function_name ();

在内部,未声明的函数被认为是返回类型为int并且接受任意数量的参数。它也与您的实际函数匹配。所以没问题。

答案 2 :(得分:1)

这取决于编译器。有些编译器会发出错误,有些则会发出警告,而其他编译器则会发出错误。编译器任务只是检查您是否使用具有正确参数的函数。如果你没有声明它,那么编译器不能检查并警告你滥用该函数,但它可以生成调用该函数的代码。 另一方面,链接器任务是看到函数被实现并将其地址放在编译器先前生成的调用中。由于您的函数已实现,链接器工作正常。

由于您的编译器没有检查您,您可以尝试使用参数调用您的函数。调用可能会起作用,但也可能导致程序崩溃。

答案 3 :(得分:1)

int a = testfunc();

int testfunc() {
    return 1;
}

您没有收到任何错误,因为在C中默认功能签名是相同的。

如果您希望编译器告诉您看下面的演示:

如果没有前向声明就这样调用,看看编译器会给你错误。

int a=testfunc(5.4);

int testfunc(float f)
{
 return 1;
}

注意:C中的最佳做法是提供您将在程序中使用它的forward declaration个函数。

答案 4 :(得分:1)

编译器不需要查看函数定义来调用它,它只需要一个 prototype 来检查参数,如果没有,编译器会假设该函数返回int并且您知道自己在做什么。但是,链接时如果链接器无法解析符号,则会出现错误。

答案 5 :(得分:1)

在ANSI C中,您不必声明函数原型;但是,使用它们是最佳实践。 如果您没有原型,并且调用了函数,编译器将根据您传递给函数的参数推断出原型。编译器假定它具有int返回类型。如果稍后在具有不同返回类型的同一编译单元中声明该函数,则会出现编译错误。