c程序编译流程
c语言程序从源代码到可执行文件经过四个步骤
编译预处理
编译
汇编
链接
见 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.a
和libphread.so
库文件,在链接时就要指明
1 | gcc test.o /usr/lib/i386-linux-gun/libpthread.so -o test |
为了防止每次都要输入库文件的绝对路径,Linux的环境变量
LIBRARY_PATH
用来指示默认的静态库路径
LD_LIBRARY_PATH
用来指示默认的动态库路径
静态库链接时搜索路径顺序:
- ld会去找gcc命令中的参数-L后的绝对路径
根据-l后的文件相对名称(无前缀lib与后缀文件格式)去
LIBRARY_PATH
/lib
/usr/lib
/usr/local/lib
(这是当初compile gcc时写在程序内的)
中找
动态链接时、执行时搜索路径顺序:
- ld会去找gcc命令中的参数-L后的绝对路径
根据-l后的文件相对名称(无前缀lib与后缀文件格式)去
LD_LIBRARY_PATH
配置文件
/etc/ld.so.conf
中指定的动态库搜索路径/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,现在才赶在学编译原理之前弄懂完整的编译流程,丢人的,褪裙吧