什么是链接器
当你写代码时,通常会把程序拆成很多个 .c 文件(模块化),每个文件里可能还调用了别人的库函数(比如 printf 或 malloc)。链接器的工作就是把这些散落在各处的“零件”装配成一个可以跑的“成品”(可执行文件)。
1. 链接器在哪个位置?
在程序从源代码变成软件的过程中,它处于最后一步:
- 预处理 (Preprocessing) :处理宏定义、包含头文件。
- 编译 (Compiling) :把 C 代码变成汇编代码。
- 汇编 (Assembling) :把汇编变成机器能懂的二进制“目标文件”(
.obj或.o)。 - 链接 (Linking) : 链接器把所有的目标文件和库文件粘在一起。
2. 链接器具体干了啥?(两个核心任务)
A. 符号解析 (Symbol Resolution)
你在 main.c 里写了 extern char hello[];,但这个 hello 数组其实定义在 data.c 里。
- 编译器 :看到
extern时会说:“好吧,我相信你以后能找到它,先给你留个空位。” - 链接器 :它会翻遍所有的模块,找到
data.c里的hello真实地址,然后把main.c里的那个“空位”填上。
这就是为什么如果你只声明了函数却没写实现,链接器会报错
undefined reference(未定义的引用)。
B. 重定位 (Relocation)
每个模块(.o 文件)在刚生成时,都以为自己是从地址 0 开始的。
- 链接器把这些模块合在一起时,会给它们重新分配地盘。比如 A 模块放在 100 号房,B 模块放在 500 号房。
- 它会修改代码里的所有跳转地址(比如
jmp或call),确保程序跑的时候能跳到正确的位置。