编译器在何处找到“printf”
Where the compiler find ``printf``?
我已经有一段时间没有接触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
的实现?如果是,如何找到它们?
非常感谢!
如果您在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)
您可以通过在自己的C库中传递-nostdlib
和链接来禁用libc
的链接。还有其他方法可以替换C库提供的定义,比如在自己的malloc
中进行链接等等。链接器只允许为任何给定的声明找到一个定义,并且由于C中没有名称篡改,所以很容易做到这一点。
这是一个过于简单化的解释,没有提到内置程序、数学库等
printf
是标准库的一部分,由于默认情况下由C编译器链接,因此被称为"标准"。标准库通常由操作系统或编译器提供。在大多数linux系统上,它位于libc.so
中,而在MS上,Windows C库由Visual C运行时文件msvcrt.dll
提供。
经过一番挖掘,以下解释对我来说最有意义:
短版本
头文件包含编译器需要的声明,但不包含实现。这个相应的库文件具有这些。编译器需要头文件,但不需要库;链接器需要库,而不是头文件。
长版本
头文件不包含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运行库中。这使得链接器可以很容易地找到
- 变量如何以及在何处可能没有C++关联的名称?
- 为什么 printf 在 C++ 中的执行速度比 cout 快?另外scanf比cin慢,为什么?
- 在何处放置与类方法相关的帮助程序函数C++
- 如何以及在何处使用带QT的Basler Cam实现opencv人脸检测代码
- 在何处声明序列化BOOST_CLASS_EXPORT
- 在 JavaScript 中,值的数据类型存储在何处以及如何存储?
- 如何在何处获取 MSVS 2008(32 位)编译器工具链的编译器,而无需安装 MSVS2008
- 在何处查看发布者发送的输出数据
- 在何处更改参考代码以从 HEVC 编码的视频中提取运动矢量
- 将删除运算符放置在何处以进行动态变量
- 如果常量引用延长了此右值的寿命,则此右值驻留在何处?
- 在C++中创建文件时,创建的文件保存在何处
- 常量存储在何处以及如何存储
- "printf"在 Windows 非控制台应用程序中写入何处?
- 编译器在何处找到“printf”
- 高斯的FFT;不确定在何处/如何插入值的打印语句
- c++在何处/如何正确定义静态文本
- Xcode 5 带有 %s 格式说明符的 LLVM printf 在调试控制台中不起作用
- 为什么"std::printf"和"printf"在<cstdio>C++中使用而不是<stdio.h>时都会编译?
- 在何处声明类成员模板的部分专用化