整个过程可以分为:预处理 (Preprocessing)编译 (Compilation)汇编 (Assembly)链接 (Linking)

1. 预处理 (Preprocessing)

执行工具cpp

核心任务:处理所有以 # 开头的指令。

  • 宏替换:将所有 #define 定义的宏进行文本替换。

  • 头文件包含:将 #include 指定的文件内容完整插入到当前位置。

  • 条件编译:根据 #if#ifdef 等指令过滤掉不符合条件的代码块。

  • 去注释:删除所有的代码注释。

  • 生成文件.i 文件(依然是可读的源代码,但体积巨大)。

2. 编译 (Compilation)

执行工具cc1 / cc1plus

核心任务:将预处理后的源代码转换为针对特定架构的汇编代码

  • 词法/语法分析:检查代码是否符合 C++ 语法规则 。

  • 语义分析:检查变量类型是否匹配等逻辑错误。

  • 优化:进行代码优化(如常量折叠、死代码消除)。

  • 生成文件.s 文件(汇编语言代码)。

3. 汇编 (Assembly)

执行工具as

核心任务:将汇编指令翻译成机器码(二进制)。

  • 指令映射:将汇编指令逐条对应到 CPU 的机器指令。

  • 生成文件.o.obj 文件(目标文件)。

    注意:此时的文件已经是二进制格式,但由于函数调用地址尚未确定,它还不能直接运行。


 链接 (Linking) 

这是你简历中提到“静态库/共享库” 的关键步骤。 执行工具ld

核心任务:符号解析与重定位

  1. 符号解析 (Symbol Resolution):将每个符号引用(如函数调用 foo())与符号定义关联起来。如果在其他文件找不到定义,就会报著名的 undefined reference 错误。

  2. 重定位 (Relocation):由于编译阶段各文件的地址都是从 0 开始的虚拟地址,链接器会将多个目标文件合并,为函数和变量分配最终的运行时内存地址。

静态链接 vs. 动态链接

特性 静态链接 (.a / .lib) 动态链接 (.so / .dll)
链接时间 编译时完成 程序运行时加载
执行文件大小 较大(库代码打包进程序) 较小(仅包含库的引用)
内存占用 多个程序运行会有多份库副本 多个程序共享物理内存中的一份库
更新便捷性 差(需重新编译整个程序) 好(只需替换 .so 文件)

更多推荐