2012-08-30 17 views
0

我有这两个文件:MinGW编译器不需要函数声明?

// first.c 
int main(void) { 
    putint(3); 
} 

// second.c 
#include <stdio.h> 
void putint(int n) { 
    printf("%d",n); 
    getchar(); 
} 

当我Win XP下运行gcc 4.6.1:

gcc first.c second.c -o program.exe 

它有没有问题,写3到stdout 。它不需要putint声明first.c。。这怎么可能?这是标准行为吗?

我已经在MSVC 2008 Express上测试过它,它只按照预期的声明运行。

// first.c 
void putint(int); 
int main(void) { 
    putint(3); 
} 

解决,感谢提示,这些选项有助于显示警告:

  • -Wimplicit
  • -std = C99(MinGW的4.6仍然默认使用gnu90
+0

查找“隐式函数声明” –

+0

我做到了。我很惊讶没有任何警告。我想知道为什么? –

+1

因为你没有告诉gcc警告你。查看gcc命令行用法。 –

回答

2

这是C tha的遗留“特征” t不应该在几十年前使用。你应该使用带有设置的编译器,如果你这样做,会警告你。海湾合作委员会有几个开关,你应该指定使用它&其中之一会给你一个警告。

编辑:我一直没有使用gcc,但你应该检查的开关是-pedantic,-Wall,-Wextra和-std。

接受此操作的编译器根据旧的语言定义假设,既然您认为不适合告诉它,否则函数a)返回一个int值,并且b)因为您将它传递给int(或者如果你传递了一些可以提升为int的东西),函数期望该参数是一个int。

由于@veer正确指出,这应该通常适用于您的特定情况。然而,在其他情况下,没有原型的函数的隐含假设与函数的实际签名之间的差异会使事情变得繁荣。

+1

实际上,编译器隐式定义了'extern int putint();'(即接受任何和任何参数),这恰好在这里工作:-)你不需要明确知道参数的空间量,因为'cdecl调用约定将堆栈管理委托给调用者。 – oldrinb

+0

@veer你完全正确。我一般在想,并没有仔细看这个具体案例。在其他一些相关案例中,事情可能会有所不同。如果该函数实际上在大型机器上返回了一个long,那么返回值可能不是您所期望的。类似地,如果函数需要很长时间(而且long比int大),那么它将使用其他值作为值的一部分。此外,该函数将在任何后续参数的错误位置查找。 –

2

这不仅仅适用于MinGW,而是所有标准版本的gcc。如上所述,这在C89中是合法的; gcc默认为'gnu89'(不是99),它也接受没有警告的代码。如果切换到c99或gnu99(或更高版本,如c11),默认情况下会收到警告,但仍会编译。

0

正如其他人所指出的,这是符合C标准的编译器的标准行为。命名您的文件.c部分将其置于C模式。它会有一些有趣的东西,如“内置函数”(printf()等)以及各种传统的C语言。

虽然我想补充一下其他人所说的我最近经历过的。 MS明确放弃了对C90以后的支持,他们对C90的支持很不好说。我不完全确定标准的ANSI C90代码库会在新的VS下编译,因为它基本上是C++编译器,其中有很多东西被禁用(而GCC实际上有一个C编译器)。他们这样做是为了推广C++。如果你想使用真正的C,你不能真正在MS Visual Studio中使用任何版本,除非你想在函数开始时声明所有变量等。