强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

01 - GCC 简介与历史

01 - GCC 简介与历史

了解 GCC 的诞生背景、发展历程、支持的编程语言以及编译器内部架构。


1.1 什么是 GCC

GCC(GNU Compiler Collection,GNU 编译器套件)是 GNU 项目的核心组成部分,也是开源世界中最重要的基础设施之一。它不仅是一个 C 编译器,而是一套支持多种编程语言的编译器集合。

┌─────────────────────────────────────────────────────┐
│              GCC (GNU Compiler Collection)           │
│  ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌──────┐ │
│  │  gcc  │ │  g++  │ │ gfortran│ │ gcj  │ │ gccgo│ │
│  │  C    │ │ C++   │ │Fortran│ │ Java  │ │ Go   │ │
│  └───┬───┘ └───┬───┘ └───┬───┘ └───┬───┘ └──┬───┘ │
│      └─────────┴─────────┴─────────┴─────────┘     │
│                    共享编译后端                       │
│              (优化器 · 汇编生成 · 链接)               │
└─────────────────────────────────────────────────────┘

GCC 的核心价值

特性说明
自由软件基于 GPL 许可证,任何人都可以自由使用、修改和分发
多语言支持支持 C、C++、Fortran、Go、D、Ada 等十余种语言
跨平台可运行于 Linux、macOS、Windows(MinGW/WSL)等
高度可移植支持 x86、ARM、RISC-V、MIPS、PowerPC 等数十种架构
成熟稳定30+ 年历史,经过无数项目的验证
丰富扩展内置大量扩展属性、内置函数和优化技术

1.2 GCC 的历史

诞生与早期发展

GCC 由 Richard Stallman 于 1987 年发布第一个版本,是 GNU 项目的关键组件。GNU 项目的目标是创建一个完全自由的类 Unix 操作系统。

年份版本里程碑事件
1984GNU 项目启动,Richard Stallman 发起自由软件运动
1985发布 GNU Manifesto(GNU 宣言)
1987GCC 1.0第一个版本发布,仅支持 C 语言,只能在 Sun 和 VAX 上运行
1988GCC 被移植到更多平台,获得更广泛的使用
1992GCC 2.0引入 C++ 支持(g++),重构编译器框架
1997EGCS(Experimental/Enhanced GCC)项目启动,引入社区化开发模式
1999GCC 2.95EGCS 与 GCC 主线合并,编译质量和优化能力大幅提升
2001GCC 3.0重大架构重构,引入 GIMPLE 中间表示,支持 Fortran 和 Java
2004GCC 4.0全新的 Tree-SSA 优化框架,显著提升优化能力
2012GCC 4.7实验性 C++11 支持
2014GCC 4.9引入 AddressSanitizer、UBSan
2015GCC 5.0默认标准切换为 C++14,OpenMP 4.0 支持
2017GCC 7默认标准切换为 C++17,-Og 优化改进
2019GCC 9C++20 部分支持,-fanalyzer 静态分析器
2021GCC 11C++20 完整支持,DWARF 5 默认启用
2022GCC 12-O3 改进,C++23 实验性支持,改进的 sanitizer
2023GCC 13C++23 进一步支持,Ada 2022 支持
2024GCC 14改进的 C++23/C23 支持,新的优化选项

GCC 与 EGCS 的历史

1997 年,GCC 的开发速度放缓,社区开发者启动了 EGCS(Experimental/Enhanced GNU Compiler System) 分支。EGCS 拥有更开放的开发模式和更快速的迭代。1999 年,GCC 官方正式采纳 EGCS 的开发模式,两个项目合并。这一事件深刻影响了 GCC 后来的发展——社区驱动的开放开发模式。

GCC 与 LLVM/Clang 的竞争

对比维度GCCLLVM/Clang
起源1987,GNU 项目2003,UIUC 研究项目
许可证GPLv3Apache 2.0 + LLVM Exception
架构单体式模块化(库设计)
诊断信息良好更友好,彩色输出、Fix-it Hints
编译速度中等较快
代码优化极强(尤其数值计算)强,持续追赶
平台支持更广泛(含稀有架构)主流平台(x86、ARM、RISC-V)
IDE 集成较少更好(libclang)
生态Linux 内核标配macOS/Android/iOS 默认
两者互补而非替代的关系:
  - Linux 内核: GCC 是唯一官方支持的编译器(Clang 为实验性)
  - macOS/iOS: Clang 是默认编译器
  - Android NDK: 同时支持 GCC(已弃用)和 Clang
  - 嵌入式/硬件厂商: 多数仍提供 GCC 工具链

1.3 GCC 支持的编程语言

GCC 通过前端(Front End)插件化的方式支持多种语言:

语言前端程序说明
Cgcc / ccC89/C90、C99、C11、C17、C23
C++g++C++98、C++11、C++14、C++17、C++20、C++23
FortrangfortranFortran 77/90/95/2003/2008/2018
GogccgoGo 语言的 GCC 前端
DgdcD 语言的 GCC 前端
AdagnatAda 语言的 GCC 前端(GNAT)
Modula-2gm2Modula-2 语言(GCC 12 起正式支持)
RustgccrsRust 语言前端(实验性,GCC 13+)
Objective-C/C++gcc / g++苹果 Objective-C 方言(需 GNUstep 运行时)

各语言标准支持一览

C 语言标准支持

标准GCC 选项状态
C89/C90-std=c89-ansi完全支持
C99-std=c99完全支持
C11-std=c11完全支持
C17-std=c17完全支持
C23-std=c23GCC 13+ 基本支持

C++ 标准支持

标准GCC 选项状态
C++98-std=c++98完全支持
C++11-std=c++11完全支持
C++14-std=c++14完全支持(GCC 5+ 默认)
C++17-std=c++17完全支持(GCC 8+)
C++20-std=c++20完全支持(GCC 11+)
C++23-std=c++23大部分支持(GCC 13+)

1.4 编译器架构

GCC 采用经典的 三阶段编译器架构,前端、中间件、后端分离设计:

┌──────────────────────────────────────────────────────────────────┐
│                     GCC 编译器整体架构                            │
│                                                                  │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐     │
│  │  C 前端  │   │ C++ 前端 │   │Fortran前端│   │ Go 前端  │     │
│  │  (cc1)   │   │  (cc1plus)│  │ (f951)   │   │ (go1)    │     │
│  └────┬─────┘   └────┬─────┘   └────┬─────┘   └────┬─────┘     │
│       └──────────────┴──────────────┴──────────────┘            │
│                          │                                       │
│                    GENERIC/GENERIC                               │
│                          │                                       │
│                      ┌───▼───┐                                   │
│                      │ GIMPLE│  ← 中间表示(SSA 形式)            │
│                      └───┬───┘                                   │
│                          │                                       │
│                   ┌──────▼──────┐                                │
│                   │ 优化 Passes │  ← 100+ 个优化通道              │
│                   │ Tree-SSA    │                                │
│                   └──────┬──────┘                                │
│                          │                                       │
│                      ┌───▼───┐                                   │
│                      │  RTL  │  ← 寄存器传输语言                  │
│                      └───┬───┘                                   │
│                          │                                       │
│                   ┌──────▼──────┐                                │
│                   │  RTL 优化   │                                │
│                   └──────┬──────┘                                │
│                          │                                       │
│              ┌───────────┼───────────┐                           │
│              │           │           │                           │
│         ┌────▼───┐  ┌───▼────┐ ┌───▼────┐                      │
│         │x86 后端│  │ARM后端 │ │RISC-V后端│                     │
│         └────┬───┘  └───┬────┘ └───┬────┘                      │
│              └───────────┴──────────┘                            │
│                          │                                       │
│                    ┌─────▼─────┐                                 │
│                    │  汇编输出  │  → .s 文件                      │
│                    └─────┬─────┘                                 │
│                    ┌─────▼─────┐                                 │
│                    │   汇编器   │  → .o 文件                      │
│                    │  (as/GAS) │                                 │
│                    └─────┬─────┘                                 │
│                    ┌─────▼─────┐                                 │
│                    │   链接器   │  → 可执行文件                    │
│                    │  (ld)     │                                 │
│                    └───────────┘                                 │
└──────────────────────────────────────────────────────────────────┘

前端(Front End)

前端负责词法分析语法分析,将源代码转换为编译器内部的树形中间表示(GENERIC)。

前端职责说明
词法分析(Lexing)将源代码字符流分解为 Token
语法分析(Parsing)将 Token 序列构建为抽象语法树(AST)
语义分析(Semantic)类型检查、作用域分析、符号表构建
生成 GENERIC输出与语言无关的树形中间表示
源代码 (hello.c)
#include 展开 + 宏替换(预处理)
Token 序列: int main ( ) { printf ( "hello" ) ; ... }
抽象语法树 (AST)
GENERIC 树(语言无关)

中端(Middle End)

中端负责语言无关的优化,这是 GCC 优化能力的核心。中间表示经过转换为 GIMPLE(SSA 形式)后,进入一系列优化通道(Pass)。

优化 Pass 类别示例
前端级优化常量折叠、死代码消除
GIMPLE 优化循环优化、内联、向量化、别名分析
SSA 优化公共子表达式消除、值编号、标量替换
循环优化循环展开、循环交换、循环分块、自动向量化
GCC 中包含 100+ 个优化 Pass,主要包括:
  - tree-ssa      : SSA 基础优化
  - tree-vrp      : 值范围传播
  - tree-ccp      : 条件常量传播
  - tree-licm     : 循环不变量外提
  - tree-loop     : 循环优化集
  - tree-vectorize: 自动向量化
  - tree-inline   : 函数内联

后端(Back End)

后端负责将通用中间表示转换为目标架构的机器码,包括指令选择、寄存器分配和指令调度。

后端职责说明
RTL 生成将 GIMPLE 转换为 RTL(Register Transfer Language)
指令选择将 RTL 操作映射为目标架构指令
寄存器分配将虚拟寄存器映射为物理寄存器
指令调度重排指令以充分利用流水线
代码生成输出汇编代码(AT&T 或 Intel 格式)

1.5 GCC 的编译产物

GCC 各阶段的可执行程序和文件后缀:

程序功能输入/输出
cppC 预处理器.c.i(预处理后源码)
cc1C 编译器.c.s(汇编代码)
cc1plusC++ 编译器.cpp.s
asGNU 汇编器.s.o(目标文件)
ldGNU 链接器.o → 可执行文件或库
collect2链接器前端包装 ld,处理构造/析构函数

文件后缀一览

后缀文件类型说明
.cC 源文件
.C, .cc, .cpp, .cxxC++ 源文件
.h头文件C/C++ 共用
.hpp, .hxxC++ 头文件
.i预处理后的 C 源文件跳过预处理阶段
.ii预处理后的 C++ 源文件
.s汇编源文件
.S含预处理指令的汇编文件
.o目标文件(Object)ELF 格式
.a静态库(Archive)ar 打包的 .o 集合
.so共享库(Shared Object)动态链接库
.lo共享目标文件PIC 版本的目标文件

1.6 GCC 版本命名与获取

版本号格式

GCC 版本号格式: major.minor.patch
示例: GCC 13.2.0
  - 13 : 主版本号(大版本,有架构变更)
  - 2  : 次版本号(增加功能、修正错误)
  - 0  : 补丁版本号(纯错误修复)

查看版本:
  gcc --version
  gcc -dumpversion
  gcc -dumpfullversion

获取 GCC

获取方式命令/网址说明
官网源码https://gcc.gnu.org/可从 SVN 或 Git 获取最新源码
发行版包管理apt install gcc / dnf install gcc简便,但版本可能较旧
Snapsudo snap install gcc-13Canonical 维护
手动编译从源码构建最灵活,可选组件

快速查看 GCC 信息

# 查看版本
gcc --version

# 查看编译器的编译参数(构建 GCC 时使用的选项)
gcc -v

# 查看支持的 CPU 类型
gcc --target-help

# 查看所有预定义的宏
gcc -dM -E - < /dev/null

# 列出所有已安装的语言前端
gcc -x c -v -E /dev/null 2>&1 | head -5

1.7 GCC 在开源生态中的地位

依赖 GCC 的关键项目

项目说明
Linux 内核唯一官方支持的编译器(Clang 为实验性支持)
GNU 工具链glibc、binutils、coreutils 等均依赖 GCC
GCC 运行时库libgcc、libstdc++、libgomp 等
Debian/RPM系统包默认使用 GCC 编译
HPC(高性能计算)Fortran 编译器的事实标准
嵌入式系统大多数芯片厂商的 SDK 基于 GCC

GCC 运行时库

说明
libgcc低级运行时支持库,提供软浮点、整数除法等
libstdc++C++ 标准库实现
libgompOpenMP 运行时库
libgfortranFortran 运行时库
libgoGo 语言运行时
libatomic原子操作库
libsanitizerSanitizer 运行时库(ASan、TSan、UBSan)

要点回顾

要点核心内容
GCC 定义GNU Compiler Collection,自由软件编译器套件
历史1987 年由 Richard Stallman 发布,30+ 年历史
语言支持C、C++、Fortran、Go、D、Ada、Modula-2、Rust(实验性)
架构三阶段:前端 → 中端(GIMPLE/SSA)→ 后端(RTL)
竞争对手LLVM/Clang,两者互补共存
地位Linux 内核及 GNU 工具链的核心基础设施

注意事项

GPLv3 许可证: GCC 采用 GPLv3 许可证,GCC 编译的程序的源代码不受 GPL 传染——只有修改 GCC 本身才需要开源。但 GCC 运行时库有例外条款(Runtime Library Exception)。

版本差异: 不同 GCC 版本对 C/C++ 标准的支持程度不同,开发前请确认目标版本支持的标准特性。

不要混用编译器: 用 GCC 编译的目标文件和用 Clang 编译的目标文件理论上兼容(遵循同一 ABI),但混用不同编译器版本的 C++ 标准库实现可能引发问题。


扩展阅读


下一步

02 - 安装与环境配置:学习如何在不同操作系统上安装 GCC 并配置多版本共存。