Ubuntu 22.04 GCC 安装与命令参数详解

Ubuntu 22.04 下 GCC 11.4.0 的在线/离线安装步骤与全部常用命令参数实测详解。

Linux开发与编译工具链gcc2026/10/06

Ubuntu 22.04 GCC 安装与命令参数详解

目标:在 Ubuntu 22.04 x86_64 环境下,完成 GCC 编译器从在线安装、离线安装到全部常用命令参数的真实回显验证。本文所有命令与输出均已在 Ubuntu 22.04 x86_64 环境实测通过。

一、环境信息

项目值
操作系统Ubuntu 22.04 LTS(jammy)
内核版本5.15.x(x86_64)
系统架构x86_64
包管理器apt(底层 dpkg)
软件源archive.ubuntu.com 官方源(jammy / jammy-updates / jammy-backports)
GCC 版本11.4.0(Ubuntu 11.4.0-1ubuntu1~22.04.3)
默认 C 标准GNU C17
当前用户root(文档中普通用户场景以 sudo 前缀演示)

💡 说明:Ubuntu 的 gcc 是一个“元包”,apt 中显示的版本为 4:11.2.0-1ubuntu1,其真正负责编译的底层编译器是 gcc-11 包(11.4.0)。两者关系详见“七、常见问题(FAQ)”。

二、工具概述

GCC(GNU Compiler Collection,GNU 编译器套件)是 GNU 项目发布的开源编译器集合,支持 C、C++、Objective-C、Fortran、Ada、Go 等多种语言。本文聚焦其中的 C 编译器 gcc。

GCC 的编译过程本质上是一条“驱动器”流水线:它按照输入文件的类型自动调用内部各子工具完成工作:

阶段子工具产物作用
预处理cpp(cc1 内嵌).i展开宏、处理 #include、条件编译
编译cc1.s将 C 源码翻译为汇编代码
汇编as.o将汇编代码翻译为机器码(可重定位目标文件)
链接collect2 / ld可执行文件合并目标文件与库,解析符号引用

GCC 在整个 Linux 开发生态中处于核心位置:内核、glibc、各类基础库与上层应用几乎都由它编译产出。它与 make(构建调度)、gdb(调试)、valgrind(内存检测)等工具配合,构成完整的 C/C++ 开发工具链。

💡 说明:Ubuntu 22.04 的 gcc 默认开启 PIE(位置无关可执行文件)与栈保护(-fstack-protector-strong)等安全特性,编译出的可执行文件默认就是 PIE 格式,见后续 file 命令回显。

三、在线安装方案

3.1 检查软件源配置

Ubuntu 22.04 的 apt 软件源定义在 /etc/apt/sources.list 与 /etc/apt/sources.list.d/ 目录下。执行 apt update 刷新软件包索引:

sudo apt update

回显(节选):

Hit:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
Reading package lists...
Building dependency tree...
Reading state information...
8 packages can be upgraded. Run 'apt list --upgradable' to see them.

💡 说明:apt update 只刷新软件包索引,不安装任何软件。若输出中出现 Err 或 Failed to fetch,说明软件源不可达或配置有误,需先修复软件源。

3.2 安装 gcc

sudo apt install -y gcc

回显:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
gcc is already the newest version (4:11.2.0-1ubuntu1).
gcc set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.

💡 说明:本次环境中 gcc 已是最新版本,故显示 already the newest version。若是在全新系统上首次安装,回显中会列出 Need to get ...、Get:1 ... 下载行,并提示 Setting up gcc ... 完成安装。

3.3 验证安装

gcc --version

回显:

gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

四、离线安装方案

离线安装的思路:在一台能联网的 Ubuntu 22.04 机器上用 apt 将软件包下载为 .deb 文件,拷贝到离线机器,再用 dpkg -i 安装。

4.1 下载软件包(不安装)

对尚未安装的软件包,直接执行:

sudo apt install --download-only --no-install-recommends -y gcc

⚠️ 注意:--download-only 表示只下载不安装;--no-install-recommends 表示不拉取“推荐”级别的依赖,减小下载体积。

由于本次环境中 gcc 已安装,直接执行该命令不会重复下载,回显:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
gcc is already the newest version (4:11.2.0-1ubuntu1).
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.

💡 说明:--download-only 对已安装且缓存中已有 .deb 的软件包不会重复下载。若需要强制重新下载(例如补全缓存),可追加 --reinstall 参数。

4.2 强制重新下载核心包

为了让离线安装演示完整,这里使用 --reinstall 强制重新下载 gcc 及其核心组成包(gcc 元包、gcc-11 编译器、cpp-11 预处理器、libgcc-11-dev 开发头文件):

sudo apt install --reinstall --download-only --no-install-recommends -y gcc gcc-11 cpp-11 libgcc-11-dev

回显:

Reading package lists...
Building dependency tree...
Reading state information...
0 upgraded, 0 newly installed, 4 reinstalled, 0 to remove and 8 not upgraded.
Need to get 32.7 MB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cpp-11 amd64 11.4.0-1ubuntu1~22.04.3 [10.0 MB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 gcc amd64 4:11.2.0-1ubuntu1 [5112 B]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gcc-11 amd64 11.4.0-1ubuntu1~22.04.3 [20.1 MB]
Get:4 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgcc-11-dev amd64 11.4.0-1ubuntu1~22.04.3 [2517 kB]
Fetched 32.7 MB in 4s (8765 kB/s)
Download complete and in download only mode

下载的 .deb 默认存放在 /var/cache/apt/archives/ 目录:

ls -lh /var/cache/apt/archives/*.deb

回显:

-rw-r--r-- 1 root root 9.6M Feb 12  2026 /var/cache/apt/archives/cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root  20M Feb 12  2026 /var/cache/apt/archives/gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Aug  5  2021 /var/cache/apt/archives/gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Feb 12  2026 /var/cache/apt/archives/libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb

4.3 拷贝到离线目录

sudo mkdir -p /opt/devchain-demo/gcc-ubuntu-test/offline
sudo cp /var/cache/apt/archives/*.deb /opt/devchain-demo/gcc-ubuntu-test/offline/
ls -lh /opt/devchain-demo/gcc-ubuntu-test/offline/

回显:

total 32M
-rw-r--r-- 1 root root 9.6M Oct  6 06:23 cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root  20M Oct  6 06:23 gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Oct  6 06:23 gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Oct  6 06:23 libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb

4.4 查看 deb 包元信息

dpkg-deb -I 查看软件包的控制信息(包名、版本、依赖关系等):

dpkg-deb -I /opt/devchain-demo/gcc-ubuntu-test/offline/gcc-11_*.deb

回显:

 new Debian package, version 2.0.
 size 20143406 bytes: control archive=1666 bytes.
     942 bytes,    16 lines      control
    2804 bytes,    36 lines      md5sums
 Package: gcc-11
 Version: 11.4.0-1ubuntu1~22.04.3
 Architecture: amd64
 Maintainer: Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>
 Installed-Size: 52747
 Depends: cpp-11 (= 11.4.0-1ubuntu1~22.04.3), gcc-11-base (= 11.4.0-1ubuntu1~22.04.3), libcc1-0 (>= 11.4.0-1ubuntu1~22.04.3), binutils (>= 2.38), libgcc-11-dev (= 11.4.0-1ubuntu1~22.04.3), libc6 (>= 2.34), libgcc-s1 (>= 3.0), libgmp10 (>= 2:6.2.1+dfsg), libisl23 (>= 0.15), libmpc3 (>= 1.1.0), libmpfr6 (>= 3.1.3), libstdc++6 (>= 5), libzstd1 (>= 1.4.0), zlib1g (>= 1:1.1.4)
 Recommends: libc6-dev (>= 2.13-0ubuntu6)
 Suggests: gcc-11-multilib, gcc-11-doc (>= 11), gcc-11-locales (>= 11)
 Replaces: cpp-11 (<< 7.1.1-8)
 Provides: c-compiler
 Section: devel
 Priority: optional
 Homepage: http://gcc.gnu.org/
 Description: GNU C compiler
  This is the GNU C compiler, a fairly portable optimizing compiler for C.
 Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>

💡 说明:Depends 行列出的就是安装本包所需的全部依赖,离线环境下需要把 gcc-11 及其所有依赖包一起拷贝过去(例如 cpp-11、gcc-11-base、libgcc-11-dev、binutils、libmpc3、libisl23 等),安装顺序为“依赖在前、被依赖在后”。

4.5 查看 deb 包内容列表

dpkg-deb -c 列出软件包将要释放到系统里的所有文件:

dpkg-deb -c /opt/devchain-demo/gcc-ubuntu-test/offline/gcc-11_*.deb | head -15

回显:

drwxr-xr-x root/root         0 2025-12-18 07:31 ./
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/bin/
-rwxr-xr-x root/root    928584 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-11
-rwxr-xr-x root/root     27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-ar-11
-rwxr-xr-x root/root     27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-nm-11
-rwxr-xr-x root/root     27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-ranlib-11
-rwxr-xr-x root/root    409608 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-11
-rwxr-xr-x root/root    257880 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-dump-11
-rwxr-xr-x root/root    282552 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-tool-11
-rwxr-xr-x root/root  24887264 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-lto-dump-11
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/lib/
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/lib/gcc/
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/lib/gcc/x86_64-linux-gnu/
drwxr-xr-x root/root         0 2025-12-18 07:31 ./usr/lib/gcc/x86_64-linux-gnu/11/
dpkg-deb: error: tar subprocess was killed by signal (Broken pipe)

💡 说明:回显末尾的 Broken pipe 是 head -15 提前关闭管道、dpkg-deb 仍在继续解包读取导致的正常现象,并非安装失败。可以看到 gcc-11 包主要向 /usr/bin/ 释放 x86_64-linux-gnu-gcc-11 等编译驱动及配套工具。

4.6 在离线机器上安装

将整个 offline 目录拷贝到离线机器后,用 dpkg -i 安装(依赖按顺序先装):

sudo dpkg -i /opt/devchain-demo/gcc-ubuntu-test/offline/*.deb

⚠️ 注意:dpkg -i 不会自动解决依赖。若缺少依赖包,会提示 dpkg: dependency problems。生产实践中更推荐在有网机器上把依赖一并下载(如 apt-rdepends 分析或直接 --download-only 整组下载),或使用 apt install ./xxx.deb 借助本机软件源自动补依赖。

安装完成后同样用 gcc --version 验证。

五、命令与参数详解

💡 说明:本章命令默认在测试目录 /opt/devchain-demo/gcc-ubuntu-test 下执行。测试文件包括:

  • hello.c:主程序,调用 add() 并打印结果,引用了自定义头文件 mymath.h
  • include/mymath.h:自定义头文件,声明 int add(int a, int b);
  • lib/mymath.c:add() 函数实现
  • warn.c:含未使用变量,用于警告演示
  • macro.c:含条件编译宏,用于 -D/-U 演示
  • foo.c、main.c:共享库演示
  • math_var.c、sqrt_demo.c:数学库链接演示

5.1 版本与平台信息类

5.1.1 --version:查看完整版本信息

gcc --version

回显:

gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

5.1.2 -dumpversion:输出主版本号

gcc -dumpversion

回显:

11

5.1.3 -dumpfullversion:输出完整版本号

gcc -dumpfullversion

回显:

11.4.0

💡 说明:-dumpversion 只输出主版本号 11,-dumpfullversion 输出完整的三段式版本号 11.4.0。脚本中判断编译器大版本时常用 -dumpversion。

5.1.4 -dumpmachine:输出目标平台三元组

gcc -dumpmachine

回显:

x86_64-linux-gnu

💡 说明:x86_64-linux-gnu 即 Ubuntu 的 multiarch 三元组,它决定了默认的库与头文件搜索路径(如 /usr/lib/x86_64-linux-gnu/)。

5.1.5 --help:查看帮助

gcc --help

回显(节选,头部):

Usage: gcc [options] file...
Options:
  -pass-exit-codes         Exit with highest error code from a phase.
  --help                   Display this information.
  --target-help            Display target specific command line options.
  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].
                           Display specific types of command line options.
  (Use '-v --help' to display command line options of sub-processes).
  --version                Display compiler version information.
  -dumpspecs               Display all of the built in spec strings.
  -dumpversion             Display the version of the compiler.
  -dumpmachine             Display the compiler's target processor.
  -print-search-dirs       Display the directories in the compiler's search path.
  -print-libgcc-file-name  Display the name of the compiler's companion library.
  -print-file-name=<lib>   Display the full path to library <lib>.
  -print-prog-name=<prog>  Display the full path to compiler component <prog>.
  -print-multiarch         Display the target's normalized GNU triplet, used as
                           a component in the library path.
  -print-multi-directory   Display the root directory for versions of libgcc.
  -print-multi-lib         Display the mapping between command line options and

回显(节选,尾部):

  -shared                  Create a shared library.
  -x <language>            Specify the language of the following input files.
                           Permissible languages include: c c++ assembler none
                           'none' means revert to the default behavior of
                           guessing the language based on the file's extension.

Options starting with -g, -f, -m, -O, -W, or --param are automatically
 passed on to the various sub-processes invoked by gcc.  In order to pass
 other options on to these processes the -W<letter> options must be used.

For bug reporting instructions, please see:
<file:///usr/share/doc/gcc-11/README.Bugs>.

5.2 编译四阶段:-E、-S、-c、-o

GCC 把从源码到可执行文件的完整过程拆成预处理、编译、汇编、链接四个阶段,可以用参数在任意阶段停下。

5.2.1 -E:只做预处理

-E 让 gcc 只运行预处理器,展开宏、包含头文件,输出 .i 文件:

gcc -I./include -E hello.c -o hello.i

💡 说明:-I./include 告知编译器去 include/ 目录搜索自定义头文件(hello.c 中 #include "mymath.h"),详见 5.9 节。

查看产物类型与内容:

file hello.i
head -5 hello.i

回显:

hello.i: C source, ASCII text
# 0 "hello.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2

💡 说明:# 行号 "文件名" 形式的行是预处理器添加的“行标记”(linemarkers),供后续编译与调试定位源码位置使用。

5.2.2 -S:只做编译,输出汇编

-S 把(预处理后的)源码翻译为汇编代码,输出 .s 文件:

gcc -S hello.i -o hello.s
file hello.s

回显:

hello.s: assembler source, ASCII text

5.2.3 -c:只做汇编,输出目标文件

-c 把汇编代码翻译为机器码,输出可重定位目标文件 .o:

gcc -c hello.s -o hello.o
file hello.o

回显:

hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

💡 说明:.o 是 ELF 可重定位文件(relocatable),尚未链接,不能直接执行。

5.2.4 链接生成可执行文件并运行

链接阶段把目标文件与库合并。由于 hello.c 引用了 add() 函数而其实现在 lib/mymath.c,链接时需要一并参与编译链接:

gcc hello.o lib/mymath.c -o hello
./hello

回显:

Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8

查看四个阶段的产物:

ls -l hello.i hello.s hello.o hello

回显:

-rwxr-xr-x 1 root root 16064 Oct  6 06:24 hello
-rw-r--r-- 1 root root 18106 Oct  6 06:24 hello.i
-rw-r--r-- 1 root root  1696 Oct  6 06:24 hello.o
-rw-r--r-- 1 root root   849 Oct  6 06:24 hello.s

用 file 查看最终可执行文件:

file hello

回显:

hello:   ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0e8db20d74fc60d737baa2a6ebd2d9964df85413, for GNU/Linux 3.2.0, not stripped

💡 说明:pie executable 表示 Ubuntu 22.04 默认开启 PIE(位置无关可执行文件);dynamically linked 表示动态链接;not stripped 表示符号表未被剥离,可用于调试。

5.3 输出文件控制:-o

-o 指定输出文件名:

gcc -I./include hello.c lib/mymath.c -o hello2
./hello2

回显:

Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8

⚠️ 注意:-o 后面必须紧跟输出文件名。若省略 -o,gcc 默认输出到当前目录的 a.out:

gcc -I./include hello.c lib/mymath.c
ls -l a.out
./a.out

回显:

-rwxr-xr-x 1 root root 16064 Oct  6 06:24 a.out
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8

5.4 优化级别:-O0、-O1、-O2、-O3

-O 系列参数控制编译器的优化强度。数字越大优化越激进,编译时间与代码体积通常随之增加,运行效率提升:

gcc -O0 -I./include hello.c lib/mymath.c -o hello_O0
gcc -O1 -I./include hello.c lib/mymath.c -o hello_O1
gcc -O2 -I./include hello.c lib/mymath.c -o hello_O2
gcc -O3 -I./include hello.c lib/mymath.c -o hello_O3
ls -l hello_O0 hello_O1 hello_O2 hello_O3

回显:

-rwxr-xr-x 1 root root 16064 Oct  6 06:24 hello_O0
-rwxr-xr-x 1 root root 16072 Oct  6 06:24 hello_O1
-rwxr-xr-x 1 root root 16072 Oct  6 06:24 hello_O2
-rwxr-xr-x 1 root root 16072 Oct  6 06:24 hello_O3

💡 说明:-O0 不做优化,编译最快,最利于调试;-O1 做基本优化;-O2 是发布版本的常用级别;-O3 进一步激进优化。小程序在体积上差异不大,可借助 size 查看各段实际大小:

size hello_O0 hello_O3

回显:

   text    data     bss     dec     hex filename
   1596     608       8    2212     8a4 hello_O0
   1598     608       8    2214     8a6 hello_O3

💡 说明:text 是代码段字节数,-O3 优化后 text 段略大(1598 > 1596);data 是已初始化数据段,bss 是未初始化数据段。

5.5 警告选项:-Wall、-Wextra、-Werror

5.5.1 -Wall -Wextra:开启常用警告

-Wall 开启一组常用警告(如未使用变量、隐式类型转换等),-Wextra 开启更多额外警告。以 warn.c(含未使用变量)为例:

gcc -Wall -Wextra warn.c -o warn

回显:

warn.c: In function 'main':
warn.c:5:9: warning: unused variable 'unused_var' [-Wunused-variable]
    5 |     int unused_var = 42;
      |         ^~~~~~~~~~

💡 说明:警告不影响编译结果,warn 可执行文件照常生成,但强烈建议消除所有警告。

5.5.2 -Werror:把警告升级为错误

-Werror 将一切警告视为错误,导致编译失败。

⚠️ 注意:-Werror 本身不会主动开启警告,必须配合 -Wall 等警告选项才有意义。单独使用 gcc -Werror warn.c 时,未使用变量警告默认未开启,编译会正常通过。

正确用法:

gcc -Wall -Werror warn.c -o warn_err
echo "exit=$?"

回显:

warn.c: In function 'main':
warn.c:5:9: error: unused variable 'unused_var' [-Werror=unused-variable]
    5 |     int unused_var = 42;
      |         ^~~~~~~~~~
cc1: all warnings being treated as errors
exit=1

⚠️ 注意:cc1: all warnings being treated as errors 表明所有警告被当作错误,编译以非零状态退出(exit=1),且不会生成 warn_err 文件。CI(持续集成)构建中常用 -Wall -Werror 强制代码零警告。

5.6 语言标准:-std=c11、-std=c17、-std=gnu17

-std= 指定遵循的 C 语言标准。c11/c17 为纯 ISO 标准模式,gnu17 为带 GNU 扩展的标准模式(Ubuntu 22.04 默认):

gcc -std=c11 -I./include hello.c lib/mymath.c -o hello_c11
./hello_c11

回显:

Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
gcc -std=c17 -I./include hello.c lib/mymath.c -o hello_c17
./hello_c17

回显:

Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
gcc -std=gnu17 -I./include hello.c lib/mymath.c -o hello_gnu17
./hello_gnu17

回显:

Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8

💡 说明:-v 输出中的 GNU C17 表明本机默认标准为 GNU C17(等价于 -std=gnu17)。常见的还有 c99、c2x(C23 草案)等取值。

5.7 调试与剖析:-g、-pg

5.7.1 -g:生成调试信息

-g 让编译器在产物中写入 DWARF 调试信息,供 gdb 断点、查看变量等使用:

gcc -g -I./include hello.c lib/mymath.c -o hello_g
file hello_g

回显:

hello_g: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=31c7bb076583bafa86200314ff4b732be4809b7f, for GNU/Linux 3.2.0, with debug_info, not stripped

💡 说明:file 输出中的 with debug_info 即表明带调试信息。调试版体积明显更大(hello_g 17672 字节,普通版 16064 字节)。发布版本应去掉 -g(或使用 -g0)。

5.7.2 -pg:生成剖析(profiling)支持

-pg 在生成的可执行文件中加入 gprof 剖析支持,运行程序会生成 gmon.out 剖析数据:

gcc -pg -I./include hello.c lib/mymath.c -o hello_pg
ls -l hello_pg

回显:

-rwxr-xr-x 1 root root 16536 Oct  6 06:25 hello_pg

💡 说明:运行 ./hello_pg 后会在当前目录生成 gmon.out,再用 gprof hello_pg gmon.out 即可输出各函数耗时统计,用于性能瓶颈分析。

5.8 宏定义:-D、-U、-dM -E

5.8.1 -D:定义宏

-DDEBUG=1 等价于在源码最前面写 #define DEBUG 1。以 macro.c 为例(含 #ifdef DEBUG 条件编译):

gcc -DDEBUG=1 -o macro macro.c
./macro

回显:

DEBUG mode: macro DEBUG is defined

不定义 DEBUG 时编译则走 else 分支:

gcc -o macro_none macro.c
./macro_none

回显:

normal mode

5.8.2 -U:取消宏定义

-UDEBUG 等价于 #undef DEBUG,可取消命令行或头文件中已定义的宏:

gcc -DDEBUG=1 -UDEBUG -o macro_u macro.c
./macro_u

回显:

normal mode

💡 说明:先用 -DDEBUG=1 定义,再用 -UDEBUG 取消,最终 #ifdef DEBUG 不成立,输出 normal mode。

5.8.3 -dM -E:列出预定义宏

-dM 让预处理器把所有宏定义(含编译器内置宏)以 #define 形式打印,-E 表示只做预处理,- 表示从标准输入读取空文件:

gcc -dM -E - </dev/null | head -20

回显:

#define __SSP_STRONG__ 3
#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 0xffff
#define __ATOMIC_ACQUIRE 2
#define __FLT128_MAX_10_EXP__ 4932
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
#define __GCC_IEC_559_COMPLEX 2
#define __UINT_LEAST8_TYPE__ unsigned char
#define __SIZEOF_FLOAT80__ 16
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 0xff
#define __SCHAR_WIDTH__ 8
#define __WINT_MAX__ 0xffffffffU
#define __FLT32_MIN_EXP__ (-125)
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __SIZE_MAX__ 0xffffffffffffffffUL
#define __WCHAR_MAX__ 0x7fffffff
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1

💡 说明:这些是编译器根据目标平台自动预定义的宏,可用于源码中判断编译器与平台特性,例如 __SIZE_MAX__ 表示 size_t 最大值。

5.9 依赖列表与头文件搜索:-MM、-M、-I

5.9.1 -MM:输出用户头文件依赖

-MM 只输出源文件对用户头文件(非系统头文件)的依赖,供 Makefile 自动生成依赖规则:

gcc -I./include -MM hello.c

回显:

hello.o: hello.c include/mymath.h

5.9.2 -M:输出全部依赖

-M 输出包括系统头文件在内的全部依赖:

gcc -I./include -M hello.c

回显(节选,输出很长):

hello.o: hello.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/features-time64.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/timesize.h \
 /usr/include/x86_64-linux-gnu/sys/cdefs.h \

💡 说明:-M 输出可用 gcc -M hello.c > hello.d 重定向到文件,由 Makefile 以 -include hello.d 引入,实现头文件变更自动重编译。

5.9.3 -I:指定头文件搜索目录

-I<目录> 向编译器追加头文件搜索路径。hello.c 中 #include "mymath.h" 位于 include/ 目录,不加 -I 会报错 fatal error: mymath.h: No such file or directory:

gcc -I./include -c hello.c -o hello.o

回显:无输出(成功)

💡 说明:-c 只编译不链接,用于验证头文件能被正确找到。-I 可多次使用(-I dir1 -I dir2),搜索顺序按命令行先后排列,系统头文件目录在最后。

5.10 库链接:-L、-l、-lm

5.10.1 -lm:链接数学库 libm

sqrt()、sin() 等数学函数位于 libm 数学库中。以 math_var.c(运行时变量参数,阻止常量折叠)为例,不加 -lm 链接失败:

gcc math_var.c -o math_var

回显:

/usr/bin/ld: /tmp/cc1K8TKE.o: in function `main':
math_var.c:(.text+0x3a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

加上 -lm 后链接成功:

gcc math_var.c -lm -o math_var
./math_var

回显:

sqrt(9) = 3.0

💡 说明:-l<名字> 表示链接名为 lib<名字>.so(或 .a)的库,-lm 即链接 libm。若源码中对 sqrt() 传的是编译期常量,GCC 会内建优化为常量结果(gcc sqrt_demo.c -o sqrt_demo 也能成功),因此演示用变量参数确保真实触发链接需求。

5.10.2 -L:指定库文件搜索目录

链接自定义库时,用 -L<目录> 告知链接器去哪个目录找库文件,配合 -l<名字> 使用:

gcc main.c -L. -lfoo -o app

回显:无输出(成功)

💡 说明:-L. 表示在当前目录(.)搜索库文件,-lfoo 表示链接 libfoo.so。详见 5.12 节完整演示。

5.11 工具链信息:-v、-print-search-dirs、-print-file-name

5.11.1 -v:输出详细编译过程

-v(verbose)让 gcc 打印其配置信息与每个内部子工具的调用细节:

gcc -v -I./include hello.c lib/mymath.c -o hello_v

回显(节选):

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04.3' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=...,amdgcn-amdhsa=... --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04.3)

继续输出内部子工具调用与头文件搜索路径:

 /usr/lib/gcc/x86_64-linux-gnu/11/cc1 -quiet -v -I ./include -imultiarch x86_64-linux-gnu hello.c -quiet -dumpdir hello_v- -dumpbase hello.c -dumpbase-ext .c -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccc3FNGg.s
GNU C17 (Ubuntu 11.4.0-1ubuntu1~22.04.3) version 11.4.0 (x86_64-linux-gnu)
        compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP
#include "..." search starts here:

💡 说明:从 -v 可以看到:默认标准是 GNU C17;--enable-default-pie 解释了为何可执行文件是 PIE 格式;-fstack-protector-strong 等安全选项由发行版默认注入。

5.11.2 -print-search-dirs:打印搜索目录

gcc -print-search-dirs

回显:

install: /usr/lib/gcc/x86_64-linux-gnu/11/
programs: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/
libraries: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/11/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/11/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/

💡 说明:programs 是 gcc 查找 cc1、as、ld 等子工具的目录列表,libraries 是查找库文件的目录列表。

5.11.3 -print-file-name:打印库/头文件完整路径

gcc -print-file-name=include
gcc -print-file-name=libgcc.a

回显:

/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/lib/gcc/x86_64-linux-gnu/11/libgcc.a

💡 说明:-print-file-name=<名字> 输出指定库或文件的完整路径,脚本中常用它动态获取路径,避免硬编码。

5.12 共享库编译:-shared、-fPIC

5.12.1 编译共享库 libfoo.so

-fPIC 生成位置无关代码(Position Independent Code),-shared 生成共享库:

gcc -shared -fPIC -o libfoo.so foo.c
file libfoo.so

回显:

libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=9691b5e25065705ea521fd67d96d2412271e173c, not stripped

💡 说明:shared object 即共享库类型。查看其动态导出符号:

nm -D libfoo.so | head -12

回显:

                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w __cxa_finalize@GLIBC_2.2.5
                 w __gmon_start__
0000000000001119 T foo
                 U puts@GLIBC_2.2.5

💡 说明:T foo 表示 foo 是已定义的导出符号(可被外部调用),U puts@GLIBC_2.2.5 表示 puts 是未定义的导入符号,来自 glibc。

5.12.2 链接并使用共享库

gcc main.c -L. -lfoo -o app

回显:无输出(成功)

💡 说明:-L. 指定库搜索目录为当前目录,-lfoo 链接 libfoo(自动匹配 libfoo.so)。

查看动态链接依赖:

ldd app

回显(相关行):

        libfoo.so => not found

⚠️ 注意:运行时动态链接器默认不搜索当前目录,libfoo.so 显示 not found。需通过 LD_LIBRARY_PATH 指定运行期库路径:

LD_LIBRARY_PATH=. ./app

回显:

hello from libfoo.so

💡 说明:LD_LIBRARY_PATH=. 告诉动态链接器去当前目录找共享库。生产环境更推荐把库安装到系统目录(如 /usr/local/lib)并执行 ldconfig 更新缓存。

六、配置说明

6.1 默认编译标准

Ubuntu 22.04 的 gcc-11 默认标准为 GNU C17(-std=gnu17),-v 输出中 GNU C17 ... 即为证明。需要严格 ISO 标准时显式传 -std=c17 或 -std=c11。

6.2 多版本共存与默认 gcc

Ubuntu 通过符号链接管理默认编译器版本。查看 /usr/bin 下的 gcc 符号链接:

ls -l /usr/bin/gcc*

回显:

lrwxrwxrwx 1 root root  6 Aug  5  2021 /usr/bin/gcc -> gcc-11
lrwxrwxrwx 1 root root 23 Dec 18  2025 /usr/bin/gcc-11 -> x86_64-linux-gnu-gcc-11
lrwxrwxrwx 1 root root  9 Aug  5  2021 /usr/bin/gcc-ar -> gcc-ar-11
lrwxrwxrwx 1 root root 26 Dec 18  2025 /usr/bin/gcc-ar-11 -> x86_64-linux-gnu-gcc-ar-11
lrwxrwxrwx 1 root root  9 Aug  5  2021 /usr/bin/gcc-nm -> gcc-nm-11
lrwxrwxrwx 1 root root 26 Dec 18  2025 /usr/bin/gcc-nm-11 -> x86_64-linux-gnu-gcc-nm-11
lrwxrwxrwx 1 root root 13 Aug  5  2021 /usr/bin/gcc-ranlib -> gcc-ranlib-11
lrwxrwxrwx 1 root root 30 Dec 18  2025 /usr/bin/gcc-ranlib-11 -> x86_64-linux-gnu-gcc-ranlib-11

💡 说明:/usr/bin/gcc 是一个符号链接,指向 gcc-11。系统中可以同时安装多个 GCC 大版本(如 gcc-10、gcc-11、gcc-12),通过 gcc-11、gcc-12 直接调用指定版本。

直接调用指定大版本:

gcc-11 --version

回显:

gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

若需要让 gcc 在多个版本间切换,可配置 update-alternatives 机制。本机尚未配置,执行查询会报错:

update-alternatives --list gcc

回显:

update-alternatives: error: no alternatives for gcc

💡 说明:Ubuntu 官方源的 gcc 默认不注册 alternatives(避免破坏符号链接链)。如需切换默认版本,可手工注册,例如:update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110。

6.3 相关环境变量

环境变量作用
LD_LIBRARY_PATH指定动态链接器运行时搜索共享库的额外目录(见 5.12)
CPATH指定编译器搜索头文件的额外目录(等效于全局 -I)
LIBRARY_PATH指定链接器搜索库文件的额外目录(等效于全局 -L)
CFLAGS供 make 等构建工具读取的 C 编译选项

七、常见问题(FAQ)

7.1 为什么 apt show gcc 显示 4:11.2.0-1ubuntu1,而 gcc --version 显示 11.4.0?

因为 Ubuntu 的 gcc 是元包,只负责把真正的编译器 gcc-11 拉进来。元包版本号与底层编译器版本可以不同:

apt-cache show gcc | head -14

回显:

Package: gcc
Architecture: amd64
Version: 4:11.2.0-1ubuntu1
Priority: optional
Section: devel
Source: gcc-defaults (1.193ubuntu1)
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 50
Provides: c-compiler, gcc-x86-64-linux-gnu (= 4:11.2.0-1ubuntu1)
Depends: cpp (= 4:11.2.0-1ubuntu1), gcc-11 (>= 11.2.0-1~)
Recommends: libc6-dev | libc-dev

💡 说明:Depends: gcc-11 (>= 11.2.0-1~) 表明元包依赖 gcc-11。以 gcc --version 输出为准(11.4.0),4:11.2.0-1ubuntu1 中的 4: 是 Debian/Ubuntu 的 epoch(版本优先级前缀)。

7.2 -Werror 为什么没有报错?

-Werror 只负责“把警告当错误”,不负责“开启警告”。未使用变量等警告默认关闭,必须配合 -Wall 等选项:

gcc -Wall -Werror warn.c -o warn_err

7.3 undefined reference to 'sqrt' 是什么原因?

sqrt 等数学函数在 libm 库中,链接时需显式加 -lm:

gcc math_var.c -lm -o math_var

7.4 libfoo.so => not found 怎么办?

运行时动态链接器不搜索当前目录。两种做法:其一,运行前设置环境变量 LD_LIBRARY_PATH=.;其二,将库安装到系统目录并执行 sudo ldconfig。

7.5 提示 file: command not found?

最小化系统可能未安装 file 工具:

sudo apt install -y file

7.6 头文件报 No such file or directory?

源码引用的自定义头文件不在默认搜索路径中,用 -I 指定目录,例如:

gcc -I./include hello.c lib/mymath.c -o hello

八、卸载与清理

8.1 查看 gcc 包的安装状态

dpkg -l 列出包的期望/实际状态(ii 表示已正确安装):

dpkg -l gcc

回显:

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version           Architecture Description
+++-==============-=================-============-=================================
ii  gcc            4:11.2.0-1ubuntu1 amd64        GNU C compiler

💡 说明:第一列 ii:第一位 i(Desired=Install)第二位 i(Status=Inst),即“期望安装且已安装”。

8.2 卸载 gcc

仅卸载元包(保留依赖与配置):

sudo apt remove gcc

连同配置与自动安装的依赖一起清理(生产环境谨慎使用,可能移除其他依赖 gcc 的工具):

sudo apt purge gcc
sudo apt autoremove

⚠️ 注意:卸载会连带影响依赖 gcc 的软件(如内核模块编译、部分 SDK),卸载前先确认无其他软件需要它。

8.3 清理下载缓存

sudo apt clean

💡 说明:apt clean 清空 /var/cache/apt/archives/ 下的 .deb 缓存,释放磁盘空间(本机缓存约 32 MB)。

九、参考链接