【问题标题】:Why doesn't the compiler need to be passed the respective source files when including headers from the standard library?为什么编译器在包含标准库中的头文件时不需要传递相应的源文件?
【发布时间】:2021-08-10 07:10:45
【问题描述】:

当您包含标题时

#include "foo.h"

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

#include <stdio.h>

编译时不必再写gcc main.c stdio.c,直接写gcc main.c即可。

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

【问题讨论】:

  • 根据编译器自动链接 C 标准库(或其中的一部分)。是的,链接器通常知道标准库的存储位置。
  • "libraries" 包括带有库实现的头文件和二进制文件。您include 标头和link 库。标准 C 库会自动链接。其他库通过-llibname 链接。
  • 顺便说一句:对于各种 C 标准函数,您仍然需要手动告诉链接器包含数学库
  • 在 GCC 和 Clang 中添加 -nostdlib 可以手动链接。但除此之外,编译器通常会为您链接标准库。
  • 注意:并非所有通用链接器(或包含/自动管理链接器的通用编译器)都知道标准库的位置。头文件(包含)文件也是如此。编译器/链接器可能会使用一些“技巧”,并且他们可能知道库和头文件所在的一些标准路径。旧的 C 编译器如 TC、QC 需要设置个性化的 libraries 和 headers。在我们的时代,在大多数情况下,安装编译器会为代码编译在标准情况下成功创建必要的环境。

标签: c compilation linker header


【解决方案1】:

当您有一个名为foo.h 的头文件时,并不一定意味着应该有一个与之关联的名为foo.c 的源文件。可以有独立的源文件和头文件。

当你编译一个简单的 C 代码时,hello_world.c

#include <stdio.h>
int main() {
   // printf() displays the string inside quotation
   printf("Hello, World!");
   return 0;
}

当您编译代码时,首先对代码进行预处理,作为头文件包含的一部分,并搜索要包含并存在于 &lt;/&gt; (#include &lt;stdio.h&gt; in our case) 中的任何头文件当前目录中的定义和编译器(预处理器)已经知道的一些预定义搜索路径。很少有标准的头文件定义,例如 /usr/include、/usr/local/include 等。more info

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

【讨论】:

    【解决方案2】:

    当你包含一个头文件 /* ... */ 你还需要一个源文件

    不,您不必这样做。

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

    【讨论】:

      猜你喜欢
      • 2014-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多