c语言的链接环节

c程序编译流程

c语言程序从源代码到可执行文件经过四个步骤

  1. 编译预处理

  2. 编译

  3. 汇编

  4. 链接

Linux GCC常用命令 - ggjucheng - 博客园 的解释

# include <stdio.h>

我们的代码中的#include <stdio.h>的作用是将该头文件中函数的**声明(declaration)**拷贝过来,使程序通过编译

此时,编译生成的.s文件中并没有实现函数功能的代码,程序只知道去调用一个叫做printf()的函数,而不知道这个函数在哪

要到第四步链接(link)时,程序才能找到printf()的实现

但是我们链接时只需要执行

1
gcc test.o -o test    # no other lib

就能生成包含输入输出功能的可执行文件,这是因为编译器悄悄地帮你链接了libc

链接

以Linux环境下的gcc为例

Linux环境下,静态链接库文件后缀.a,动态链接库文件后缀.so

链接指令

经过汇编后产生的.o二进制文件需要与代码中include的对应的库文件链接后才能生成最后的可执行文件。例如,多线程编程用到了libpthread.alibphread.so库文件,在链接时就要指明

1
gcc test.o /usr/lib/i386-linux-gun/libpthread.so -o test

为了防止每次都要输入库文件的绝对路径,Linux的环境变量

LIBRARY_PATH用来指示默认的静态库路径

LD_LIBRARY_PATH用来指示默认的动态库路径

静态库链接时搜索路径顺序:

  1. ld会去找gcc命令中的参数-L后的绝对路径

根据-l后的文件相对名称(无前缀lib与后缀文件格式)去

  1. LIBRARY_PATH

  2. /lib /usr/lib /usr/local/lib (这是当初compile gcc时写在程序内的)

中找

动态链接时、执行时搜索路径顺序:

  1. ld会去找gcc命令中的参数-L后的绝对路径

根据-l后的文件相对名称(无前缀lib与后缀文件格式)去

  1. LD_LIBRARY_PATH

  2. 配置文件/etc/ld.so.conf中指定的动态库搜索路径

  3. /lib /usr/lib

中找

链接实现

静态链接:将静态库的二进制代码链接到源.o文件中,以后可以独立运行

动态链接:将动态库的信息链接到源.o文件中,运行时到相关位置去寻找二进制代码

libc

libc(libc.a, libc.so) 是 C stand library 的实现,包括stdio.h string.h stdlib.h的头文件的实现,编译器默认自动链接,这就是为什么链接时我们不需要手动指定stdio.h的库

libc实现了math.h,但在一些平台下依然需要手动指定libm


大一开始学C,现在才赶在学编译原理之前弄懂完整的编译流程,丢人的,褪裙吧