gcc 如果我只包含头文件,编译器如何找出我的代码中将使用哪个动态链接库,哪里没有描述它?

ivqmmu1c  于 2022-11-13  发布在  其他
关注(0)|答案(5)|浏览(201)

如果我只包含头文件,编译器如何找出我的代码中将使用哪个动态链接库,哪里没有描述它?

#include <stdio.h>
void main()
{
    printf("Hello world\n");
}

有我只包括

stdio.h

我的代码被用来

printf function

如何知道,在头文件原型,宏和常量被描述,但没有关于在哪个文件“printf”是实现。那么它是如何工作的?

ggazkfy8

ggazkfy81#

当你编译一个可运行的可执行文件时,你不仅要指定源代码,还要指定一个库列表,从这些库中可以查找到未定义的引用。对于C标准库,这是隐式的(除非你告诉GCC -nostdinc),所以你可能没有意识到这一点。
库只被链接器使用,而不是编译器。链接器定位库中所有未定义的引用。如果库是静态的,链接器只会将实际的机器码添加到最终的可执行文件中。另一方面,如果库是共享的,链接器只记录名称(和版本?)。然后是 loader 的工作以便在加载时找到合适的库并即时解决缺少的依赖项。
在Linux上,您可以使用ldd来列出动态链接的可执行文件的加载时间依赖项,例如,尝试ldd /bin/ls。(在MacOS上,您可以使用otool -L来实现相同的目的。)

x8diyxa7

x8diyxa72#

正如其他人所回答的,标准c库是隐式链接的。如果你正在使用gcc,你可以使用-Wl,--trace选项来查看链接器在做什么。
我测试了您的示例代码:

gcc -Wl,--trace main.c

提供:

/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.6/crtbegin.o
/tmp/ccCjfUFN.o
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc_s.so)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc_s.so)
/usr/lib/gcc/x86_64-linux-gnu/4.6/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crtn.o

这表示连接器正在使用libc.so(以及ld-linux.so)。

ryhaxcpt

ryhaxcpt3#

GCC默认链接glibc库。在构建可执行文件时,不需要提及-l library。因此,您会发现printf函数和glibc中的其他函数不需要任何独占链接。

1rhkuytd

1rhkuytd4#

从技术上讲,编译器并不知道要使用哪些库。链接器(通常是ld)会这样做。头文件只告诉编译器库函数使用的接口,并让链接器来确定它们在哪里。
一个源文件在变成可执行文件之前会有一个很长的路径。
c-[预处理]〉i -[编译]〉s -[汇编]〉o -[链接]〉a.out
当您调用cc source.c时,所有这些步骤都是一次透明地完成的,并且标准库(通常为libc.so)和可执行加载程序(通常为crt0.o)链接在一起。
任何附加库必须作为附加链接器标志(即-lpthread)传递。

qgzx9mmu

qgzx9mmu5#

我会说这取决于IDE或者编译器和系统。头文件只包含接口信息,比如函数参数的名称,它期望任何属性,其他的,这就是编译器如何首先将你的代码转换成一个中间目标文件。然后是链接,在代码中printf通过静态库或动态库被添加到可执行文件中。
函数和其他工具(如STL)是C/C++的一部分,因此它们要么由编译器提供,要么由系统提供。例如,在Solaris上,除非使用gcc,否则没有C库的调试版本。但在Visual Studio上,您有调试版本msvcrt.dll,并且还可以静态链接C库。
简而言之,答案是C库中printf和其他函数的代码是由编译器在链接时添加的。

相关问题