「Linux 系统编程」gcc 编译及常用参数
0 什么是 gcc
在 Linux 系统中,gcc(GNU Compiler Collection)是将 C、C++ 等源代码编译成可执行程序的核心工具。
gcc 编译程序的简单示例:
1 |
|
如果是 C++ 程序,通常采用 g++(gcc 的 C++ 特殊版本):
1 |
|
1 gcc 编译过程
gcc 编译主要分为四个阶段,分别为 预处理、编译、汇编、链接。
-
预处理 (Preprocessing)
处理源代码中 以
#
开头的指令(如#include
,#define
,#ifdef
等),展开头文件内容、进行宏替换、条件编译等。添加参数
-E
可以生成对应的预处理之后的代码(.i
文件)。例如:1
gcc -E source.c -o preprocessed.i
-
编译 (Compilation)
将预处理后的源代码(
.i
文件)翻译成特定处理器架构的 汇编语言(.s
文件)。添加参数
-S
可以生成对应的编译之后的汇编语言文件:1
gcc -S preprocessed.i -o assembly.s
或直接
gcc -S source.c -o assembly.s
。 -
汇编 (Assembly)
将汇编语言文件(
.s
文件)翻译成 机器指令(目标代码),生成 可重定位目标文件(.o
文件)。添加参数
-S
可以生成对应的汇编之后的目标文件:1
gcc -c assembly.s -o object.o
或直接
gcc -c source.c -o object.o
-
链接 (Linking)
将一个或多个 .o 文件合并,并解析这些文件中的符号引用(如函数名、全局变量名)。
将引用的符号与其定义(可能在同一个 .o 文件、其他 .o 文件或预编译的库 .a / .so 中)关联起来。
将程序 与所需的系统库(如标准 C 库 libc)链接,并分配最终的内存地址(布局)。
最终 输出可执行文件。默认为
a.out
,可以添加-o
指定输出文件名。
2 gcc 常用编译参数
2.1 基础编译和输出控制
-
-o <output_file>
:指定输出文件名,1
gcc test.c -o my_test # 指定输出文件名为 my_test
-
-c
:只进行预处理、编译和汇编,生成.o
目标文件,1
gcc -c my_utils.c # 生成目标文件 my_utils.o
2.2 调试信息
-
-g
:可执行文件或目标文件中生成调试信息(供 gdb 使用)。1
gcc -g test.c -o debug_test
2.3 程序优化
-
O0
: 关闭优化(默认)。编译快,适合调试。 -
O1, -O2, -O3
: 递增的优化级别。-O2
通常是最佳平衡点(性能提升显著,编译时间可接受,调试影响相对小);-O3
激进优化,可能增加代码大小或轻微改变行为。1
gcc -O2 main.c -o fast_program
-
Os
: 优化代码大小。 -
Ofast
: 启用所有-O3
优化,并放宽严格标准合规性以追求更快速度(可能影响浮点精度等)
2.4 警告控制
-
-Wall
: 启用 绝大多数 常用警告。1
gcc -Wall test.c -o program
-
-Wextra
: 启用-Wall
不包括的额外警告。1
gcc -Wall -Wextra test.c -o program
-
-Werror
: 将所有警告视为 错误。强制要求 消除警告才能编译成功。1
gcc -Wall -Werror test.c -o program
-
-w
: 关闭所有警告。
2.5 头文件和库路径
-
-I <directory>
: 添加 头文件 搜索路径。1
gcc test.c -o program -I/path/to/my/includes
-
-L <directory>
: 添加 库文件 搜索路径。1
gcc test.c -o program -lmylib -L/path/to/my/libs
-
-l <library>
: 链接指定的库。库名需去掉前缀lib
和后缀(.a
/.so
)。1
2gcc test.c -o program -lm # 链接数学库 libm.so
gcc test.c -o program -lpthread # 链接 POSIX 线程库 libpthread.so
2.6 宏定义
-
-D <macro>[=value]
:在命令行定义宏。常用于条件编译。1
2gcc -D DEBUG test.c -o program # 定义宏 DEBUG
gcc -D VERSION=\"1.0\" test.c -o program # 定义宏 VERSION 并赋值
2.7 标准版本
-
-std=<standard>
: 指定要遵循的语言标准。1
gcc -std=c11 test.c -o program # 使用 C11 标准
1
gcc -std=c++17 test.cpp -o program # 使用 C++17 标准
2.8 静态链接
-
-static
: 强制链接器进行静态链接。程序包含所有依赖库的副本,体积大,但运行时不再依赖系统库版本。1
gcc -static main.c -o static_program
2.9 生成位置无关代码 (PIC/PIE)
-
-fPIC
/-fPIE
: 生成位置无关代码。-fPIC
主要用于创建共享库(.so
),-fPIE
用于创建位置无关的可执行文件(增强安全性 ASLR)。1
2gcc -fPIC -shared helper.c -o libhelper.so # 创建共享库
gcc -fPIE -pie main.c -o pie_program # 创建 PIE 可执行文件