GCC(GNU Compiler Collection)和 G++ 是 GNU 项目中用于编译 C 和 C++ 代码的工具。以下是它们的基本用法和相关命令,输出参数统一放在最后。
gcc [选项] 输入文件 [输出文件]
-c
:仅编译源文件,生成目标文件(.o
文件),不进行链接。-E
:仅进行预处理,输出预处理后的文件。-S
:编译源文件并生成汇编代码。-Wall
:启用所有常见警告。-O
:优化级别(如 -O2
、-O3
)。-I<目录>
:添加头文件搜索路径。-L<目录>
:添加库文件搜索路径。-l<库名>
:链接指定的库(如 -lm
链接数学库)。编译单个 C 文件并生成可执行文件
gcc hello.c -o hello
编译多个 C 文件并生成可执行文件
gcc main.c utils.c -Wall -o myprogram
仅编译源文件生成目标文件
gcc -c utils.c -o utils.o
编译并链接生成可执行文件,启用优化
gcc -O2 main.c utils.c -o optimized_program
包含头文件和库文件的编译
gcc -I/path/to/includes -L/path/to/libs main.c -lmylib -o myapp
G++ 是 GCC 的一部分,专门用于编译 C++ 代码。其用法与 GCC 类似,但默认处理 C++ 代码,输出参数同样放在最后。
![[Pasted image 20250221101414.png]]
g++ [选项] 输入文件 [输出文件]
-c
:仅编译源文件,生成目标文件(.o
文件),不进行链接。-E
:仅进行预处理,输出预处理后的文件。-S
:编译源文件并生成汇编代码。-Wall
:启用所有常见警告。-O
:优化级别(如 -O2
、-O3
)。-std=<标准>
:指定 C++ 标准(如 -std=c++17
)。-I<目录>
:添加头文件搜索路径。-L<目录>
:添加库文件搜索路径。-l<库名>
:链接指定的库(如 -lm
链接数学库)。编译单个 C++ 文件并生成可执行文件
g++ hello.cpp -o hello_cpp
编译多个 C++ 文件并生成可执行文件
g++ main.cpp utils.cpp -Wall -o mycppapp
仅编译源文件生成目标文件
g++ -c utils.cpp -o utils.o
编译并链接生成可执行文件,启用优化并指定 C++ 标准
g++ -O2 -std=c++17 main.cpp utils.cpp -o optimized_cppapp
包含头文件和库文件的编译
g++ -I/path/to/includes -L/path/to/libs main.cpp -lmycpplib -o mycppapp
特性 | GCC(GNU C 编译器) | G++(GNU C++ 编译器) |
---|---|---|
主要用途 | 编译 C 语言代码 | 编译 C++ 语言代码 |
默认链接库 | 链接 C 标准库 | 链接 C++ 标准库(包括 STL 等) |
支持的编程语言 | 主要支持 C,通过子命令支持其他语言(如 g++ 支持 C++) |
专门支持 C++ |
使用场景 | 适用于纯 C 项目或需要混合编译多种语言的项目 | 适用于纯 C++ 项目或需要使用 C++ 特性的项目 |
编译选项 | 大部分选项与 G++ 共享,但某些 C++ 特有的选项仅适用于 G++ | 包含所有 GCC 选项,并增加了一些 C++ 特有的选项,如 -std=c++17 |
使用 GCC:
使用 G++:
C++ 代码的编译过程通常分为四个主要阶段:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly) 和 链接(Linking)。每个阶段都有特定的任务,最终将源代码转换为可执行文件。以下是详细的编译过程说明:
任务:处理源代码中的预处理指令,如 #include
、#define
、#ifdef
等。
主要操作:
#include
指令替换为对应头文件的内容。#define
定义的宏。工具:预处理器(如 cpp
),在GCC/G++中,预处理器是编译过程的一部分。
示例命令:
g++ -E main.cpp -o main.i
这条命令会将 main.cpp
进行预处理,并将结果输出到 main.i
文件中。
示例:
预处理后的 main.i
文件将包含
的内容,并将 PI
替换为 3.14159
。
任务:将预处理后的源代码翻译成汇编语言代码。
工具:编译器前端(如 clang
、gcc
的前端)
示例命令:
g++ -S main.i -o main.s
这条命令会将预处理后的文件 main.i
编译成汇编代码,并将结果输出到 main.s
文件中。
示例:
生成的汇编代码可能如下所示:
section .data
msg db 'Pi is 3.14159',0xA
section .text
global _start
_start:
; write syscall
mov eax, 1
mov ebx, 1
mov ecx, msg
mov edx, 14
int 0x80
; exit syscall
mov eax, 60
xor edi, edi
syscall
任务:将汇编语言代码转换为目标机器的机器码,生成目标文件(Object File)。
主要操作:
工具:汇编器(如 as
、nasm
),在GCC/G++中,汇编器是编译过程的一部分。
示例命令:
g++ -c main.s -o main.o
这条命令会将汇编代码 main.s
转换为目标文件 main.o
。
示例:
生成的 main.o
文件包含机器码和符号表。
任务:将一个或多个目标文件与所需的库文件链接,生成最终的可执行文件。
主要操作:
工具:链接器(如 ld
、gold
),在GCC/G++中,链接器是编译过程的一部分。
示例命令:
g++ main.o -o myprogram
这条命令会将目标文件 main.o
链接成最终的可执行文件 myprogram
。
多文件示例:
假设有两个源文件 main.cpp
和 utils.cpp
,可以按以下步骤编译和链接:
预处理:
g++ -E main.cpp -o main.i
g++ -E utils.cpp -o utils.i
编译:
g++ -S main.i -o main.s
g++ -S utils.i -o utils.s
汇编:
g++ -c main.s -o main.o
g++ -c utils.s -o utils.o
链接:
g++ main.o utils.o -o myprogram
或者,使用单个命令完成所有步骤:
g++ main.cpp utils.cpp -o myprogram
假设有以下 C++ 代码:
// main.cpp
#include
int add(int a, int b);
int main() {
int sum = add(3, 4);
std::cout << "Sum: " << sum << std::endl;
return 0;
}
// utils.cpp
int add(int a, int b) {
return a + b;
}
编译步骤:
预处理:
g++ -E main.cpp -o main.i
g++ -E utils.cpp -o utils.i
编译:
g++ -S main.i -o main.s
g++ -S utils.i -o utils.s
汇编:
g++ -c main.s -o main.o
g++ -c utils.s -o utils.o
链接:
g++ main.o utils.o -o myprogram
最终生成的 myprogram
可执行文件可以运行,输出:
Sum: 7
"add.h"
)-I
选项指定了额外的包含路径,编译器会在这些路径中查找。假设有以下目录结构:
project/
├── src/
│ ├── main.cpp
│ └── add.h
└── include/
└── utils.h
在 main.cpp
中包含 add.h
:
#include "add.h"
编译时,编译器会首先在 src/
目录下查找 add.h
。
)在C和C++编程中,包含头文件时使用引号 ("add.h"
) 和尖括号 (
) 会影响编译器搜索头文件的路径。这两者的主要区别在于编译器查找头文件的位置和优先级。以下是详细的解释:
CPLUS_INCLUDE_PATH
)也可以影响搜索路径。假设 add.h
位于系统的标准包含路径中:
#include
编译器会在其标准包含路径中查找 add.h
,而不会考虑当前源文件所在的目录。可以使用 -I
选项指定包含路径(假设在src路径下,命令如下)。
bash
g++ -I. main.cpp -o myprogram
特性 | "add.h" |
|
---|---|---|
搜索优先级 | 当前目录 → 用户指定目录 → 标准包含路径 | 标准包含路径 |
使用场景 | 项目内部头文件、相对路径引用 | 标准库头文件、第三方库头文件 |
灵活性 | 更灵活,适用于需要引用本地或相对路径的头文件 | 不灵活,适用于全局或系统范围内的头文件 |
示例 | #include "mylib.h" |
#include |