当你包含一个标题
#include "foo.h"
您还需要一个源文件foo.c
,其中包含编译时传递给编译器的头文件中原型的定义:gcc main.c foo.c
。为什么标准库的头文件不需要同样的处理?例如,假设您有一个包含
main.c
文件#include <stdio.h>
当你编译的时候,你不需要写gcc main.c stdio.c
,你只需要写gcc main.c
。
为什么会这样?编译器/链接器知道在哪里寻找源文件时,你编译和只是自动添加它们?如果不是,那么编译器如何知道如何处理函数原型呢?
当您有一个名为foo.h
的头文件时,这并不一定意味着应该有一个名为foo.c
的源文件与之关联。可以有独立的源文件和头文件。
当你编译一个简单的C代码时,hello_world.c
#include <stdio.h>
int main() {
// printf() displays the string inside quotation
printf("Hello, World!");
return 0;
}
当您编译代码时,代码首先作为头文件包含的一部分进行预处理,并且在</>
(#include <stdio.h> in our case
)中包含的任何头文件都会在当前目录中搜索它的定义,并且编译器(预处理器)已经知道一些预定义的搜索路径。一些标准的头文件定义存在,如/usr/include,/usr/local/include等。更多信息
你问题的第二部分是关于编译器如何知道printf()
的定义例如,当我们在编译时不关联源文件时,这是因为当你编译任何程序时,编译器默认将其链接到一个名为libc
的std C库,该库包含scanf,printf等函数的定义
当你包含标题/*…*/你还需要一个源文件
不,你不需要。
- 头文件可以只包含宏和数据类型声明。不需要源文件
- 之前编译过的代码,您只有库或目标文件。你需要让链接器知道它必须使用这些文件。
- 使用标准库文件。通用链接器需要知道库的位置。许多编译器自己传递此信息。例如,gcc使用规范文件,你可以指定你的库在哪里(以及更多的东西)。