Linux 学习笔记(八):GCC 编译器的四大阶段与链接原理

一、 代码是如何变成程序的?

在 Linux 下,我们习惯用 gcc hello.c -o hello 一键编译。但这背后其实经历了四个极其清晰的阶段(面试高频考点):

  1. 预处理(-E) :展开头文件、宏替换、去注释。生成 .i 文件。

  2. 编译(-S) :检查语法,将 C 代码翻译成汇编语言。生成 .s 文件。

  3. 汇编(-c) :将汇编代码翻译成机器指令,生成二进制的目标文件 .o。

  4. 链接:将目标文件与库文件结合起来,生成最终的可执行文件。

二、 动态链接 vs 静态链接

如果程序用到了标准库函数(如 printf),链接阶段就要把库连进来。

  • 静态链接(.a):把库代码直接拷贝进可执行文件。优点是运行不依赖环境;缺点是文件大、占内存、更新困难。

  • 动态链接(.so) :程序运行时才去加载共享库。优点是文件小、省内存;缺点是环境缺失会导致无法运行。

    Linux 下 GCC 默认使用动态链接。

三、 实战:用指令拆解编译过程

bash

复制代码
# 1. 预处理
gcc -E hello.c -o hello.i
# 2. 编译(生成汇编)
gcc -S hello.i -o hello.s
# 3. 汇编(生成二进制目标文件)
gcc -c hello.s -o hello.o
# 4. 链接
gcc hello.o -o hello

四、 实用工具:file 与 ldd

  • file hello:可以查看文件类型,验证它是一个 dynamically linked(动态链接)的可执行文件。

  • ldd hello:列出该程序依赖的所有动态库(如 libc.so.6),排查库缺失问题时的利器。

总结

以前只知道敲 gcc,现在明白了"预处理 -> 编译 -> 汇编 -> 链接"的底层逻辑。这不仅是语法,更是操作系统运行程序的基石。

自我实战操作

在云服务器上,你需要先确认装了 gcc。如果没装,执行 sudo apt install -y gcc。

实战 1:剥洋葱式看编译过程
bash 复制代码
cd ~/linux_study
mkdir gcc_test
cd gcc_test
vim hello.c

(在 vim 里写一段简单代码,按 Esc 后敲 :wq 保存)

cpp 复制代码
#include <stdio.h>
#define PI 3.14
int main() {
    printf("Hello GCC! PI = %f\n", PI);
    return 0;
}

接下来,我们一步步"拆解"它:

bash 复制代码
# 1. 预处理:把展开头文件、替换宏(把 PI 换成 3.14)
gcc -E hello.c -o hello.i
# 用 vim 或者 cat 看看 hello.i,你会发现代码变得极长,PI 全变成了 3.14

# 2. 编译:变成汇编代码
gcc -S hello.i -o hello.s
# 用 vim 看看 hello.s,你能看到类似 mov, push 这种汇编指令

# 3. 汇编:变成二进制目标文件(无法直接 cat 看,会乱码)
gcc -c hello.s -o hello.o

# 4. 链接:生成最终可执行文件
gcc hello.o -o hello

# 5. 运行
./hello

实战 2:验证动态链接(装逼神技)
bash 复制代码
# 查看 hello 这个程序到底是什么类型的文件
file hello

# 查看 hello 依赖了哪些动态库(会看到 libc.so.6,这就是 C 标准库)
ldd hello

# 看看 hello.o 和 hello 的体积差异(链接后变大了,因为引入了库信息)
ls -l hello.o hello
相关推荐
StarsGreen24 分钟前
libva在intel平台上的前端流程简介
linux
YueTann1 小时前
mgtv5th-baseline学习
学习
蒸蒸yyyyzwd3 小时前
从后端面经学到的 3 个知识
笔记·学习
17岁的勇气3 小时前
Unity Shader unity文档学习笔记(二十二):shader变体
笔记·学习·unity
坤坤子吖3 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
Felven5 小时前
华为鲲鹏920s芯片serdestool工具使用说明
linux·运维·服务器·华为·鲲鹏920·serdestool
路灯上の马陈5 小时前
Java 内部类 学习笔记
笔记·学习
莫晓燚5 小时前
mall 电商项目完整部署---实战
linux·运维·docker·容器
咋的啥名都用不了呢~5 小时前
Linux项目部署5(安装Nginx的插件)
linux
希和20275 小时前
51 单片机入门笔记:江科大课程代码逐行讲解(按键控制 LED 流水灯)
笔记·单片机·mongodb