GCC
在大多数 Linux 发行版中,GCC (GNU Compiler Collection) 是默认的 C 语言编译器,你可以通过在终端输入 gcc --version 来检查是否已安装。

最基本的编译命令
假设你有一个名为 hello.c 的 C 语言源文件。
(hello.c):**
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
编译并运行
最简单的编译命令是:
gcc hello.c
这条命令会做以下几件事:
- 调用 GCC 编译器。
- 编译
hello.c文件。 - 生成一个默认的可执行文件,在 Linux 上,这个文件默认名为
a.out。
运行生成的可执行文件:
./a.out
输出:
Hello, World!
指定输出文件名
默认的 a.out 名字并不直观,我们可以使用 -o 选项来指定输出的可执行文件名。
命令:
gcc hello.c -o hello
说明:
-o:指定输出文件的名称。hello:你想要生成的可执行文件的名字(通常不加扩展名,但加上也可以)。
运行:
./hello
输出:
Hello, World!
注意: -o 后面跟着的是你想要的输出文件名,而不是源文件名,一个常见的错误是写成 gcc -o hello.c hello,这会尝试生成一个名为 hello 的文件,但内容是把 hello 作为源文件来编译,通常会报错。
分步编译(推荐用于大型项目)
对于大型项目,通常会将编译过程分为四个步骤:预处理、编译、汇编、链接,理解这个过程有助于你更好地掌握编译原理。
预处理
预处理处理以 开头的指令,如 #include(包含头文件)、#define(宏定义)等。
gcc -E hello.c -o hello.i
-E:只进行预处理。- 输出文件
hello.i是一个经过预处理后的 C 语言源文件,它会把所有#include的头文件内容直接插入到源文件中。
编译
编译器将预处理后的代码(.i 文件)转换成汇编代码。
gcc -S hello.i -o hello.s
-S:将代码编译成汇编代码,但不进行汇编。- 输出文件
hello.s是包含汇编指令的文本文件。
汇编
汇编器将汇编代码(.s 文件)转换成机器语言,生成目标文件(Object File),目标文件是机器码,但还不能直接运行,因为它缺少一些必要的部分(printf 函数的具体实现)。
gcc -c hello.s -o hello.o
-c:将代码汇编成目标文件,但不进行链接。- 输出文件
hello.o是一个二进制文件,包含了机器码和符号表等信息,你可以使用file命令查看:file hello.o。
链接
链接器将一个或多个目标文件(.o 文件)和所需的库文件链接在一起,生成最终的可执行文件。
gcc hello.o -o hello
- 链接器会找到
hello.o中引用的外部函数(如printf),并从标准 C 库(libc)中找到其实际地址,然后合并所有代码和数据,生成最终的可执行文件hello。
运行:
./hello
常用编译选项
GCC 提供了非常丰富的选项来控制编译过程。
1 警告选项
开启警告可以帮助你发现代码中的潜在问题。
-
-Wall(We All warnings):开启所有常见的警告。这是最常用、最重要的警告选项。gcc -Wall hello.c -o hello
-
-Wextra:开启一些额外的、不那么常见的警告。gcc -Wall -Wextra hello.c -o hello
-
-Werror:将所有警告都当作错误处理,如果代码有任何警告,编译会失败,这对于保证代码质量非常有用。gcc -Wall -Werror hello.c -o hello
2 调试选项
-g:在生成的可执行文件中包含调试信息,这样你就可以使用 GDB 等调试工具来调试你的程序。gcc -g hello.c -o hello_debug
使用 GDB 调试:
gdb ./hello_debug
3 优化选项
-
-O0:不进行优化,这是默认选项,编译速度最快,调试最方便。gcc -O0 hello.c -o hello_no_opt
-
-O1或-O:进行基本优化,在代码大小和执行速度之间取得平衡。 -
-O2:推荐使用的优化级别,在-O1的基础上进行更高级的优化,但不会显著增加编译时间。gcc -O2 hello.c -o hello_optimized
-
-O3:最高级别的优化,可能会显著增加代码大小,并且有时可能导致一些意想不到的问题(比如影响浮点精度)。 -
-Os:针对代码大小进行优化,适用于嵌入式系统或对存储空间有严格要求的场景。
4 链接外部库
如果你的程序使用了外部库(例如数学库 libm),需要使用 -l 选项来链接。
示例 (math.c):
#include <stdio.h>
#include <math.h> // 使用 math.h 中的 sqrt 函数
int main() {
double result = sqrt(16.0);
printf("The square root of 16 is %f\n", result);
return 0;
}
编译命令:
gcc math.c -o math -lm
-lm:告诉链接器链接数学库。m是libm.so或libm.a去掉lib和.so/.a后的前缀。- 顺序很重要:源文件(
.c或.o)放在前面,库文件(-lxxx)放在后面。
编译多个源文件
一个项目通常由多个 .c 文件组成,GCC 可以一次性编译它们。
文件结构:
.
├── main.c
└── utils.c
main.c
#include "utils.h"
#include <stdio.h>
int main() {
int a = 10, b = 20;
printf("The sum of %d and %d is %d\n", a, b, add(a, b));
return 0;
}
utils.c
#include "utils.h"
int add(int x, int y) {
return x + y;
}
utils.h
#ifndef UTILS_H #define UTILS_H int add(int x, int y); #endif
编译命令:
gcc main.c utils.c -o my_app
GCC 会依次编译 main.c 和 utils.c,然后将它们链接成一个名为 my_app 的可执行文件。
更专业的做法(推荐):
# 1. 分别编译成目标文件 gcc -c main.c -o main.o gcc -c utils.c -o utils.o # 2. 链接所有目标文件 gcc main.o utils.o -o my_app # 3. 运行 ./my_app
这种方法的好处是,如果你只修改了 main.c,你只需要重新编译 main.c 并链接即可,而不需要重新编译 utils.c,这在大型项目中能节省大量时间。
总结表格
| 命令/选项 | 功能 | 示例 |
|---|---|---|
gcc file.c |
基本编译,生成 a.out |
gcc hello.c |
gcc file.c -o name |
编译并指定输出文件名 | gcc hello.c -o hello |
gcc -E file.c |
只进行预处理 | gcc -E hello.c -o hello.i |
gcc -S file.i |
编译成汇编代码 | gcc -S hello.i -o hello.s |
gcc -c file.s |
汇编成目标文件 | gcc -c hello.s -o hello.o |
gcc file.o |
链接目标文件生成可执行文件 | gcc hello.o -o hello |
-Wall |
开启所有常见警告 | gcc -Wall hello.c -o hello |
-Wextra |
开启额外警告 | gcc -Wall -Wextra hello.c -o hello |
-Werror |
将警告视为错误 | gcc -Wall -Werror hello.c -o hello |
-g |
生成调试信息 | gcc -g hello.c -o hello_debug |
-O0, -O1, -O2, -O3 |
设置优化级别 | gcc -O2 hello.c -o hello |
-lm |
链接数学库 | gcc math.c -o math -lm |
gcc file1.c file2.c |
编译多个源文件 | gcc main.c utils.c -o my_app |
掌握这些命令和选项,你就可以在 Linux 环境下自如地编译和管理你的 C 语言项目了。
