C++ 编译全流程实战示例详解

 更新时间:2026年06月05日 09:40:09   作者:c++之路  
C++ 编译的全流程可以分为几个主要步骤,包括预处理、编译、汇编和链接,本文完整梳理 C++ 从源代码到可运行程序的四大核心阶段:预处理 → 编译 → 汇编 → 链接,覆盖原理、指令、细节与实战示例

本文完整梳理 C++ 从源代码到可运行程序的四大核心阶段预处理 → 编译 → 汇编 → 链接,覆盖原理、指令、细节与实战示例,是理解 C++ 程序运行机制的核心笔记。

一、C++ 编译总览

一个 .cpp 源文件要变成可执行程序,必须经过4个标准步骤,缺一不可:

源代码(.cpp/.h)
    ↓ 【预处理】预处理器 cpp
预处理文件(.ii)
    ↓ 【编译】编译器 cc1plus
汇编文件(.s)
    ↓ 【汇编】汇编器 as
目标文件(.o/.obj)
    ↓ 【链接】链接器 ld
可执行文件(.out/.exe)

工具链:GCC/Clang 会自动调用上述 4 个工具,我们只需一条编译命令即可完成全流程。

二、第一步:预处理(Preprocessing)

2.1 什么是预处理

预处理是编译前的文本替换工作,由预处理器完成,不检查语法,只做纯文本处理。

2.2 预处理核心工作

  1. 删除注释
    单行注释 //、多行注释 /* */ 全部删除。
  2. 展开头文件
    #include <xxx> / #include "xxx" 会把头文件内容完整复制到当前文件。
  3. 宏替换
    #define 定义的宏,进行文本替换(不做计算)。
  4. 条件编译
    根据 #ifdef / #ifndef / #else / #endif 决定保留/删除代码。
  5. 添加行号与文件名标记
    方便后续报错定位。

2.3 预处理指令一览

指令作用
#include插入头文件内容
#define定义宏
#undef取消宏定义
#ifdef / #ifndef判断宏是否存在
#if / #else / #endif条件编译
#pragma once防止头文件重复包含
#pragma message编译时打印信息
#error强制报编译错误

2.4 实战:生成预处理文件

使用 GCC/Clang 生成预处理后的 .ii 文件:

# 只执行预处理,生成 main.ii
g++ -E main.cpp -o main.ii
clang++ -E main.cpp -o main.ii

打开 main.ii 可以看到:

  • 头文件全部展开
  • 宏全部替换
  • 注释消失

三、第二步:编译(Compilation)

3.1 什么是编译

预处理文件 → 汇编代码,是 C++ 最核心阶段。

3.2 编译核心工作

  1. 语法/语义检查
    报错:缺少分号、类型不匹配、函数未定义等。
  2. 语法分析 → 生成抽象语法树(AST)
  3. 优化代码
    根据 -O1/-O2/-O3 优化执行效率、体积。
  4. 生成汇编代码(.s 文件)
    输出对应平台汇编指令(人类可读的底层指令)。

3.3 实战:生成汇编文件

# 执行到编译阶段,生成汇编文件 main.s
g++ -S main.ii -o main.s
# 或直接从源码一步生成
g++ -S main.cpp -o main.s

main.s 是汇编代码,包含 movaddcall 等底层指令。

四、第三步:汇编(Assembly)

4.1 什么是汇编

汇编代码 → 二进制目标文件,由汇编器 as 完成。

4.2 核心工作

  • 将汇编指令翻译成机器码(二进制)
  • 生成目标文件(Linux:.o,Windows:.obj
  • 文件是二进制格式,不可直接运行(缺少库函数地址)

4.3 实战:生成目标文件

# 执行到汇编阶段,生成 main.o
g++ -c main.s -o main.o
# 直接从源码生成 .o
g++ -c main.cpp -o main.o

五、第四步:链接(Linking)

5.1 什么是链接

把多个目标文件 + 静态库/动态库 → 单个可执行文件

5.2 链接核心工作

  1. 合并所有目标文件的代码与数据
  2. 地址重定位
    给函数、变量分配最终内存地址
  3. 解析外部符号
    找到 coutprintfstd::string 等标准库实现
  4. 生成最终可执行文件
    Linux:a.out,Windows:.exe

5.3 静态链接 vs 动态链接

类型说明优点缺点
静态链接把库代码复制到可执行文件不依赖外部文件,可直接运行文件体积大,更新库需重新编译
动态链接只记录库路径,运行时加载文件小,库可共享更新运行必须依赖对应库文件

5.4 实战:最终链接生成可执行文件

# 链接 .o 文件,生成可执行程序 app
g++ main.o -o app
# 直接一键完成 4 步
g++ main.cpp -o app

运行:

./app   # Linux/macOS
app.exe # Windows

六、完整一键编译四阶段指令速查

从源码直接执行每一步:

# 1. 预处理 → .ii
g++ -E main.cpp -o main.ii
# 2. 编译 → .s
g++ -S main.cpp -o main.s
# 3. 汇编 → .o
g++ -c main.cpp -o main.o
# 4. 链接 → 可执行文件
g++ main.o -o app

一键全流程:

g++ main.cpp -o app -std=c++17 -O2

七、关键知识点总结

  1. 预处理:纯文本处理,#include#define、删除注释
  2. 编译:语法检查、优化、生成汇编代码
  3. 汇编:汇编 → 二进制目标文件(.o
  4. 链接:合并文件、解析库、生成可执行程序
  5. 目标文件不可运行:因为没有链接外部函数地址
  6. 头文件不参与编译:只在预处理阶段展开,真正编译的是 .cpp

八、常见编译错误对应阶段

错误发生阶段
头文件找不到预处理
宏使用错误预处理
语法错误、类型错误编译
函数未定义实现链接
库找不到链接

总结

  1. C++ 编译固定四步:预处理 → 编译 → 汇编 → 链接
  2. 预处理负责文本替换,编译负责语法与优化,链接负责生成最终程序
  3. 掌握编译流程,能快速定位头文件、语法、链接类错误

到此这篇关于C++ 编译全流程总结的文章就介绍到这了,更多相关C++ 编译流程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法

    关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法

    这篇文章主要介绍了关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法,本文给大家介绍的非常详细,对大家的学习工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 浅析C语言中的数组及字符数组

    浅析C语言中的数组及字符数组

    这篇文章主要介绍了C语言中的数组及字符数组,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • C++实现LeetCode(89.格雷码)

    C++实现LeetCode(89.格雷码)

    这篇文章主要介绍了C++实现LeetCode(89.格雷码),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++调用python(执行py文件)的全过程

    C++调用python(执行py文件)的全过程

    这篇文章主要给大家介绍了关于C++调用python(执行py文件)的相关资料,文中通过图文以及实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-12-12
  • Qt框架中QPushButton 和 QToolButton的使用小结

    Qt框架中QPushButton 和 QToolButton的使用小结

    本文对比了Qt框架中的两种按钮控件QPushButton和QToolButton,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • C语言如何利用异或进行两个值的交换详解

    C语言如何利用异或进行两个值的交换详解

    最近在工作中遇到了两个值交换的需求,发现自己对异或有些忘记,所以索性写出来,方便以后需要的时候参考学习,下面这篇文章主要给大家介绍了关于C语言如何利用异或进行两个值的交换的相关资料,需要的朋友可以参考下。
    2017-09-09
  • strncpy与snprintf 的用法比较

    strncpy与snprintf 的用法比较

    以下是对strncpy与snprintf的具体用法以及区别进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • C++程序的五大内存分区实例详解

    C++程序的五大内存分区实例详解

    C++内存区域,一般可分为栈内存区、堆内存区、全局/静态内存区、文字常量内存区及程序代码区5大分区,本文就带大家深刻的理解这5大内存分区,感兴趣的可以了解一下
    2021-10-10
  • C++ 转换函数用法案例详解

    C++ 转换函数用法案例详解

    这篇文章主要介绍了C++ 转换函数用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • C++深入分析回顾函数重载

    C++深入分析回顾函数重载

    C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading),借助重载,一个函数名可以有多种用途
    2022-06-06

最新评论