「Linux 系统编程」gcc 编译及常用参数

0 什么是 gcc

在 Linux 系统中,gcc(GNU Compiler Collection)是将 C、C++ 等源代码编译成可执行程序的核心工具。

gcc 编译程序的简单示例:

1
2
# 将 test.c 编译为可执行文件 test
gcc test.c -o test

如果是 C++ 程序,通常采用 g++(gcc 的 C++ 特殊版本):

1
2
# 将 C++ 程序 test.cpp 编译为可执行文件 test
g++ test.cpp -o test


1 gcc 编译过程

gcc 编译主要分为四个阶段,分别为 预处理、编译、汇编、链接

  1. 预处理 (Preprocessing)

    处理源代码中 # 开头的指令(如 #include, #define, #ifdef 等),展开头文件内容、进行宏替换、条件编译等。

    添加参数 -E 可以生成对应的预处理之后的代码(.i 文件)。例如:

    1
    gcc -E source.c -o preprocessed.i
  2. 编译 (Compilation)

    将预处理后的源代码(.i 文件)翻译成特定处理器架构的 汇编语言.s 文件)。

    添加参数 -S 可以生成对应的编译之后的汇编语言文件:

    1
    gcc -S preprocessed.i -o assembly.s

    或直接 gcc -S source.c -o assembly.s

  3. 汇编 (Assembly)

    将汇编语言文件(.s 文件)翻译成 机器指令(目标代码),生成 可重定位目标文件.o 文件)。

    添加参数 -S 可以生成对应的汇编之后的目标文件:

    1
    gcc -c assembly.s -o object.o

    或直接 gcc -c source.c -o object.o

  4. 链接 (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
    2
    gcc test.c -o program -lm  # 链接数学库 libm.so
    gcc test.c -o program -lpthread # 链接 POSIX 线程库 libpthread.so

2.6 宏定义

  • -D <macro>[=value]:在命令行定义宏。常用于条件编译。

    1
    2
    gcc -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
    2
    gcc -fPIC -shared helper.c -o libhelper.so # 创建共享库
    gcc -fPIE -pie main.c -o pie_program # 创建 PIE 可执行文件

「Linux 系统编程」gcc 编译及常用参数
https://marisamagic.github.io/2025/08/11/20250810/
作者
MarisaMagic
发布于
2025年8月11日
许可协议