一、GCC 介绍
1.1 GNU 工具集
GNU 工具集由自由软件基金会发起,始于20世纪80年代初,旨在构建完全自由的操作系统,核心原则是保障用户自由使用、修改和分发软件的权利。
| 工具类别 | 工具名称 | 主要功能 | 应用场景 |
|---|---|---|---|
| 编译器 | gcc/g++ | 将 C/C++ 源代码转换为可执行程序 | 各类 C/C++ 项目开发 |
| 调试工具 | gdb | 设置断点、查看变量、分析内存,辅助代码调试 | 软件开发调试阶段,排查程序错误 |
| 项目构建工具 | make | 依据 Makefile 自动处理编译依赖 | 源文件多、依赖关系复杂的项目 |
| 目标文件分析工具 | objdump | 反汇编目标文件,查看二进制文件内容 | 分析程序底层实现,排查目标文件相关问题 |
| 链接工具 | ld | 合并多个目标文件及库文件为可执行文件 | 编译流程最后阶段,处理目标文件链接 |
| 静态库管理工具 | ar | 创建、修改和操作.a静态库文件 | 大型项目中复用通用代码模块 |
1.2 GCC 是什么?
GCC(GNU Compiler Collection)即 GNU 编译器集合,是开源的跨平台编译器,核心功能是将源代码转换为可执行文件。
- 起初用于编译 C 语言,现已支持 C++、Java 等多种语言
- 是 GNU 工具链的核心,遵循 GNU 通用公共许可证(GPL)
- 支持跨平台编译,方便在不同系统环境下进行软件开发
1.3 安装 GCC
| 操作 | 命令 | 说明 |
|---|---|---|
| 安装编译工具包 | sudo apt install build-essential | 包含 GCC 及其他相关编译工具 |
| 查看 GCC 版本 | gcc --version | 确认安装是否成功 |
💡 在 Linux 系统中,GCC 一般为预装软件,通常无需手动安装。
1.4 GCC 支持的文件类型
| 文件后缀 | 文件类型 | 含义说明 |
|---|---|---|
.c | 源代码文件 | 采用 C 语言编写的源代码文件 |
.cpp | 源代码文件 | 使用 C++ 语言编写的源代码文件 |
.h | 头文件 | 源程序中包含的头文件,用于声明函数、变量等 |
.o | 目标文件 | 源代码经过编译但尚未链接的中间文件 |
.a | 库文件(静态库) | 由目标文件构成的静态库文件 |
.so | 库文件(动态库) | 动态库文件 |
二、gcc 编译过程
2.1 默认编译(生成 a.out)
gcc 编译时默认不指定输出文件名,会自动生成a.out可执行文件。
bash
复制
# 语法格式 gcc 文件名.c # 注意:文件名不可丢掉后缀 # 示例 gcc hello.c # 生成 a.out ./a.out # 运行| 特点 | 说明 |
|---|---|
| 自动生成 | 自动生成名为a.out的可执行文件,无需指定输出名 |
| 便捷快速 | 适用于快速验证代码,初步验证代码功能 |
| ⚠️ 文件覆盖 | 多次编译会覆盖旧的a.out文件 |
| ❌ 不适用生产环境 | 正式项目中不推荐,难以区分程序功能,不便版本管理 |
2.2 指定输出文件名(推荐)
日常开发中最常用的编译方式,使用-o选项指定输出文件名。
bash
复制
# 语法格式 gcc 源文件 -o 输出文件名 # 示例 gcc hello.c -o hello # 编译生成名为 hello 的可执行文件 ./hello # 运行2.3 四步编译过程
GCC 编译背后由四个关键步骤构成:预处理 → 编译 → 汇编 → 链接
第一步:预处理(Preprocessing)
bash
复制
gcc -E 源文件.c -o 预处理后文件.i| 项目 | 说明 |
|---|---|
| 操作 | 处理#include、#define等预处理指令,将头文件内容插入,替换宏定义 |
| 产出 | 生成预处理后的文件(.i后缀) |
第二步:编译(Compilation)
bash
复制
gcc -S 预处理后文件.i -o 汇编文件.s| 项目 | 说明 |
|---|---|
| 操作 | 把预处理后的文件转为汇编语言代码,进行语法、语义分析及优化 |
| 产出 | 得到汇编语言文件(.s后缀) |
第三步:汇编(Assembly)
bash
复制
gcc -c 汇编文件.s -o 目标文件.o| 项目 | 说明 |
|---|---|
| 操作 | 将汇编代码转换为目标机器码,形成目标文件 |
| 产出 | 生成目标文件(.o后缀) |
第四步:链接(Linking)
bash
复制
gcc 目标文件.o -o 可执行文件| 项目 | 说明 |
|---|---|
| 操作 | 把目标文件与所需库文件(静态库或动态库)链接,解决函数和变量引用问题 |
| 产出 | 生成可执行文件 |
四步编译流程总览
源文件 (.c) ↓ gcc -E(预处理) 预处理文件 (.i) ↓ gcc -S(编译) 汇编文件 (.s) ↓ gcc -c(汇编) 目标文件 (.o) ↓ gcc(链接) 可执行文件2.4 gcc 常用编译选项
| 选项 | 功能 | 语法格式 | 应用场景 |
|---|---|---|---|
| -o | 指定编译输出文件的名称 | gcc 源文件 -o 输出文件名 | 日常开发中明确输出文件名称,便于管理 |
| -c | 只进行编译和汇编,不进行链接,生成目标文件 | gcc -c 源文件 | 生成目标文件用于后续链接,或单独分析目标文件 |
| -E | 仅对源文件进行预处理,输出预处理后的代码 | gcc -E 源文件 -o 预处理后文件名 | 检查预处理指令执行情况 |
| -S | 将源文件编译为汇编代码 | gcc -S 源文件 | 分析编译器生成的汇编代码,学习汇编语言 |
| -g | 生成调试信息,供调试器(如 gdb)调试 | gcc -g 源文件 | 程序调试阶段排查问题(使用 GDB 前必须加) |
| -Wall | 开启大部分常见警告信息 | gcc -Wall 源文件 | 发现代码中潜在问题,提高代码质量 |
| -std | 指定编程语言标准 | gcc -std=标准 源文件 | 确保代码按特定标准编译,增强兼容性和可移植性 |
三、gcc 多文件编程
在实际项目开发中,程序通常由多个源文件组成,需要将多个.c文件一起编译链接。
bash
复制
# 方式一:直接编译多个源文件 gcc file1.c file2.c -o 输出文件名 # 方式二:分别编译为目标文件,再链接(推荐,适合大型项目) gcc -c file1.c -o file1.o gcc -c file2.c -o file2.o gcc file1.o file2.o -o 输出文件名💡方式二(分步编译)的优势:修改某个文件时,只需重新编译该文件对应的目标文件,无需全部重编译,大幅提升编译效率。
四、GDB 介绍
4.1 什么是 GDB?
GDB 是 GNU 项目下功能强大的调试工具,主要用于调试 C/C++/Go 等编程语言编写的程序。
4.2 GDB 核心功能
| 功能类别 | 具体功能 |
|---|---|
| 运行状态检查 | 动态检查程序运行状态(变量值、内存布局、寄存器内容等) |
| 代码执行跟踪 | 跟踪代码执行流程(单步执行、断点设置、函数调用等) |
| 多线程调试 | 支持多线程调试(查看线程状态、切换线程上下文等) |
4.3 使用 GDB 前的准备
使用 GDB 调试程序前,编译时必须添加-g选项,为可执行文件添加调试信息!
bash
复制
# 编译时加 -g 选项 gcc -g -o program program.c # 说明:-g 选项告诉 GCC 在生成的可执行文件中包含调试信息, # 以便 GDB 能够识别变量名、函数名和行号等信息4.4 启动和退出 GDB
| 操作 | 命令 | 说明 |
|---|---|---|
| 启动 GDB | gdb 可执行文件名 | 启动 GDB 并加载相应的可执行文件 |
| 退出 GDB | quit或q | 在 GDB 命令行中输入后按回车键退出 |
bash
复制
# 示例:启动 GDB 调试 program gdb program # 退出 GDB (gdb) quit五、gdb 调试命令
5.1 完整调试命令表
| 命令分类 | 具体命令 | 命令说明 | 使用示例 |
|---|---|---|---|
| 程序运行控制 | run / r | 运行程序,直至遇到断点或程序结束 | r |
| 程序运行控制 | continue / c | 继续运行程序,直到下一个断点或程序结束 | c |
| 代码查看 | list / l | 列出源代码 | l(默认列当前行附近) /l main(列 main 函数代码) |
| 断点操作 | break / b | 在指定行号或函数处设置断点 | b 10(第10行设断点)/b main(main函数处设断点) |
| 断点操作 | info b | 查看已设置断点的信息 | info b |
| 断点操作 | delete / d | 删除指定编号的断点 | d 2(删除编号为2的断点) |
| 调试方式 | next / n | 逐过程调试,不进入函数内部 | n |
| 调试方式 | step / s | 单步调试,进入函数内部 | s |
| 变量查看 | print / p | 查看变量的值 | p n(查看变量 n 的值) |
| 变量查看 | display | 每次程序停止时自动显示变量的值 | display n(自动显示变量 n 的值) |
5.2 next 与 step 的区别
| 命令 | 全称 | 功能 | 适用场景 |
|---|---|---|---|
| n(next) | 逐过程 | 执行下一行,遇到函数调用直接跳过,不进入函数内部 | 不关心某函数内部逻辑时使用 |
| s(step) | 单步 | 执行下一行,遇到函数调用会进入函数内部逐行执行 | 需要跟踪某函数内部执行流程时使用 |
5.3 GDB 调试工作流程
六、速查总结
gcc 编译命令速查
| 操作 | 命令 | 说明 |
|---|---|---|
| 快速编译(默认输出) | gcc hello.c | 生成a.out |
| 指定输出文件名 | gcc hello.c -o hello | 生成hello可执行文件 |
| 仅预处理 | gcc -E hello.c -o hello.i | 生成.i预处理文件 |
| 编译为汇编 | gcc -S hello.i -o hello.s | 生成.s汇编文件 |
| 编译为目标文件 | gcc -c hello.s -o hello.o | 生成.o目标文件 |
| 链接生成可执行文件 | gcc hello.o -o hello | 链接生成可执行文件 |
| 带调试信息编译 | gcc -g -o hello hello.c | 供 GDB 调试使用 |
| 开启编译警告 | gcc -Wall hello.c -o hello | 显示潜在问题警告 |
| 多文件编译 | gcc file1.c file2.c -o out | 同时编译多个源文件 |
gdb 调试命令速查
| 命令 | 缩写 | 功能 |
|---|---|---|
run | r | 运行程序 |
continue | c | 继续运行到下一断点 |
list | l | 查看源代码 |
break 行号/函数名 | b | 设置断点 |
info b | — | 查看断点信息 |
delete 编号 | d | 删除断点 |
next | n | 逐过程执行(不进函数) |
step | s | 单步执行(进入函数) |
print 变量名 | p | 查看变量值 |
display 变量名 | — | 持续监视变量 |
quit | q | 退出 GDB |
💡核心要点:
- 编译调试程序时必须加
-g选项,否则 GDB 无法识别变量名和行号!n(next)不进入函数内部,s(step)会进入函数内部,注意区分!- 生产环境编译应使用
-o指定文件名,避免覆盖a.out