为什么编译器在包含标准库中的 headers 时不需要传递相应的源文件?

Why doesn't the compiler need to be passed the respective source files when including headers from the standard library?

当您包含 header

#include "foo.h"

您还需要一个源文件,foo.c,其中包含您在编译时传递给编译器的 header 中原型的定义:gcc main.c foo.c。为什么标准库中的 headers 不必发生同样的事情?例如,假设您有一个 main.c 文件

#include <stdio.h>

编译的时候不用再写gcc main.c stdio.c,直接写gcc main.c.

这是为什么? compiler/linker 是否知道在编译时在哪里查找源文件并自动添加它们?如果不是,那么编译器如何知道如何处理函数原型?

When you include a header /* ... */ you also need a source file

不,你不必。

  1. 您的头文件可能只包含宏和数据类型声明。不需要源文件
  2. 之前编译过代码,您只有库或目标文件。您需要让链接器知道它必须使用这些文件。
  3. 您使用标准库文件。通用链接器需要知道库的位置。许多编译器自己传递这些信息。例如 gcc 使用规范文件,您可以在其中指定库的位置(以及更多内容)。

当您有一个名为 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 等。more info

你的问题的第二部分是关于编译器如何知道 say 的定义,例如 printf() 当我们在编译时不关联源文件时,这是你编译任何程序时的原因默认情况下,编译器将其与名为 libc 的标准 C 库链接,该库包含 scanf、printf 等函数的定义