【问题标题】:Where the compiler find ``printf``?编译器在哪里找到“printf”?
【发布时间】:2016-05-11 05:37:25
【问题描述】:

我已经有一段时间没有接触 c++了,这个问题可能很愚蠢,但它确实困扰了我一段时间。

假设我有以下 c 程序:

#include <stdio.h>

int main()
{
  int i;
  for(i=0; i<10; i++)
  {
    printf("Hello World!\n");
  }
  return 0;
}

我知道我包含stdio.h 的原因是因为我在main 中调用printf,但我想知道编译器如何知道在编译期间在哪里可以找到printf() 的实现? stdio.h 只提供函数原型,但编译过程中到底发生了什么?

是否存在编译器知道的某些前缀路径来搜索printf 的实现?如果有,如何找到它们?

非常感谢!

【问题讨论】:

  • 真正找到它的是链接器。是的,查找标准库的路径是预定义的。
  • @πάνταῥεῖ 你能再解释一下吗?谢谢!
  • "链接阶段的路径查找" 对于不同的编译器,或者对于同一个编译器的不同版本是不同的。你为什么对它感兴趣?
  • 如果您想真正了解编译器/链接器正在寻找头文件和库(至少对于 gcc)的幕后情况,请参阅 stackoverflow.com/a/11481258/12711

标签: c++ c


【解决方案1】:

如果您使用的是 linux 系统,则使用的 C 库可能是 glibc。 GCC 实际上并不提供 C 库实现,只提供头文件。实际实现这些函数的定义是 C 库的工作。在 Linux 上,有一种叫做“共享库”的东西,由需要它的程序动态加载。例如:

ldd /usr/bin/gcc
    linux-vdso.so.1 (0x00007ffd9e9f8000)
    libm.so.6 => /lib64/libm.so.6 (0x00007ff9a35a6000)
    libc.so.6 => /lib64/libc.so.6 (0x00007ff9a31de000)
    /lib64/ld-linux-x86-64.so.2 (0x000055953c573000)

您可以通过传递-nostdlib 并在您自己的C 库中链接来禁用libc 的链接。还有其他方法可以替换 C 库提供的定义,例如链接到您自己的 malloc 等。链接器只允许为任何给定的声明找到 一个 定义,并且由于 C 中没有名称修饰,因此很容易做到。

这是一个过于简单的解释,并没有提到内置函数、数学库等。

【讨论】:

    【解决方案2】:

    printf 是标准库的一部分,它被称为“标准”,因为它默认由 C 编译器链接。标准库通常由操作系统或编译器提供。在大多数 linux 系统上,它位于 libc.so,而在 MS Windows C 库上,由 Visual C 运行时文件 msvcrt.dll 提供。

    【讨论】:

      【解决方案3】:

      经过一番挖掘,以下解释对我来说最有意义:

      短版

      头文件包含编译器需要的声明,但不包含实现。这 相应的库文件有那些。编译器需要头文件而不需要库;链接器 需要库,而不是头文件。

      长版

      头文件不包含printf()的定义 函数(即它的实现。)包含在 C 标准 I/O 库中(即glibc)。编译器无法创建机器指令 会导致 printf() 函数运行,因为它不知道在哪里 printf() 实施是; 它无法创建对此函数的调用。相反,编译器在可执行文件中放置一个符号 或多或少说,呼吁 printf() 必须由链接器解析。

      链接器是在编译器之后运行的独立程序。它查看所有未解析的符号 程序,例如 printf() ,并尝试通过在软件库中查找它们的位置来解决它们 程序需要的。在这种情况下,链接器需要在 C 标准 I/O 库中查找位置 的 printf() 函数,以便它可以修补代码以调用它(ldd /usr/bin/gcc 方式或gcc -v foo.c -Wl --verbose 方式)。 C 标准 I/O 库 之所以特别,是因为它几乎用于每个 C 程序,因此许多 C 实现都包含它 在 C 运行时库中。这使得链接器可以轻松找到它

      【讨论】:

        猜你喜欢
        • 2012-08-12
        • 1970-01-01
        • 2012-09-30
        • 2013-05-22
        • 1970-01-01
        • 2012-11-26
        • 1970-01-01
        • 2010-11-15
        • 2018-05-16
        相关资源
        最近更新 更多