gcc是否会自动包含一些头文件?

3

I have the following code:

int main()
{
    printf("Hello\n");
    return 0;
}

我使用以下命令进行编译:
gcc -o myprogram myfile.c

即使我没有包含#include <stdio.h>,它也没有出现任何错误。那么gcc是不是自动包含了这个头文件呢?

我的gcc版本是4.3.3。


它可能没有给出错误:但是如果你看了的话,它确实会给出警告。它对函数原型(在缺失的头文件中)进行了假设,并自动链接了库。 - Weather Vane
2个回答

3
在 ANSI C 中,您可以调用未声明的函数。第一次调用它们时,这些函数会被隐式声明。假定它们返回 int ,并根据默认参数提升采取参数。由于您没有包含 ,编译器使用这个规则,并隐式地声明了 printf。请注意,这是未定义的行为,因为像 printf 这样采用可变参数列表的函数必须明确声明。gcc 通常会警告您是否使用隐式声明规则,因为这通常不是故意使用的。

当我使用以下命令时,gcc没有给我任何警告:gcc -o myprogram myfile.c。此外,程序正常工作并打印出“Hello”。 - Tom
1
@Tom 使用 -Wall 编译 - Weather Vane
2
@chux C11 6.5.2.2/6(C89和C99有类似的文本)。标准库函数被认为是使用原型定义的。 - M.M
@melpomene:如果我没记错的话,默认为“gnu90”。 - too honest for this site
1
@chux,ISO 9899 §3.3.2.2 ¶6 在这方面非常清楚:如果表示所调用函数的表达式具有不包括原型的类型,则对每个参数执行整数提升,并将类型为 float 的参数提升为 double。[...] 如果使用包括原型的类型定义函数,并且在提升后的参数类型与参数类型不兼容,或者原型以省略号(",...")结尾,则行为是未定义的。 - fuz
显示剩余7条评论

1
不,gcc没有包含任何你未请求的头文件。#include语句是C预处理器宏(像#define或#if一样),实际上在实际的C编译之前被评估。您可以通过调用gcc -E myfile.c来查看在所有宏解析后您的代码的样子。正如您将看到的,printf仍然不会被声明。
如果使用-Wall编译,您应该会收到一个警告,指出printf未声明。但是,gcc“猜测”printf的使用方式(可能来自其参数,但也可以简单地在内部知道例程)。由于在链接时找到了匹配的符号名称,因此您不会收到错误,并且您的程序运行得非常顺利。
顺便说一下,gcc 5.3.0显示以下警告:
myfile.c: In function 'main':
myfile.c:3:5: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
     printf("Hello\n");
     ^
myfile.c:3:5: warning: incompatible implicit declaration of built-in function 'printf'
myfile.c:3:5: note: include '<stdio.h>' or provide a declaration of 'printf'

有没有一种方法可以防止gcc进行这些“猜测”? - Tom
1
或者尝试使用-Werror-implicit-function-declaration编译 - fpmurphy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接