2. GCC/G++编译器入门
说实话,很多C++初学者一上来就被各种IDE惯坏了。点一下运行按钮,代码就跑了。但你真的知道背后发生了什么吗?我个人觉得,搞C++如果不了解GCC/G++,就像开车不懂发动机——能开,但永远成不了老司机。
这一章,咱们就聊聊GCC/G++。我会从安装讲起,再到基本命令,最后把那些常用的编译选项掰开揉碎了说清楚。嗯,都是我在项目里踩过坑、流过泪换来的经验。
2.1 GCC/G++是什么?
GCC,全称GNU Compiler Collection。它是个编译器家族,支持C、C++、Java、Fortran等多种语言。G++是GCC里专门编译C++的那个工具。
说白了,GCC处理.c文件,G++处理.cpp文件。但实际工作中,我习惯直接用g++编译C++代码,省心。
核心区别:
- gcc:根据文件后缀名决定编译语言,链接时默认不链接C++标准库
- g++:默认将文件当作C++编译,自动链接C++标准库
2.2 安装GCC/G++
不同平台安装方式不一样。我当年在Windows上折腾了好久,后来发现用Linux才是最舒服的。
Linux(Ubuntu/Debian)
sudo apt update
sudo apt install build-essential
g++ --version
build-essential是个元包,会把gcc、g++、make等工具一起装好。我个人建议新手直接装这个,省得后面缺这缺那。
macOS
xcode-select --install
或者用Homebrew:
brew install gcc
Windows
Windows下我推荐用MinGW-w64。下载安装后,记得把bin目录加到系统PATH里。我曾经在这步吃过亏——装完了以为万事大吉,结果命令行里敲g++死活找不到。
注意:Windows用户安装完成后,务必打开命令行输入 g++ --version 验证。如果提示"不是内部或外部命令",那就是PATH没配好。
2.3 基本编译命令
先写个最简单的程序:
// hello.cpp
#include <iostream>
int main() {
std::cout << "Hello, GCC!" << std::endl;
return 0;
}
编译它:
g++ hello.cpp -o hello
./hello
就这么简单?对,就这么简单。但实际项目里,没人会这么干。你想想看,一个项目几十个源文件,难道每次都敲一遍?
我刚开始工作时,就是一行行敲命令。后来项目大了,发现根本记不住哪些文件需要编译。嗯,那时候我才意识到Makefile的重要性——不过那是后面章节的事了。
2.4 常用编译选项详解
这才是重点。GCC/G++的编译选项多如牛毛,但常用的也就那么十几个。我按使用频率给你排个序:
2.4.1 输出文件控制
| 选项 | 作用 | 示例 |
|---|---|---|
-o |
指定输出文件名 | g++ main.cpp -o app |
-E |
只进行预处理 | g++ -E main.cpp -o main.i |
-S |
只编译到汇编 | g++ -S main.cpp -o main.s |
-c |
只编译不链接 | g++ -c main.cpp -o main.o |
这里有个坑:-o选项必须紧跟在源文件后面,或者放在最后。我曾经写过g++ -o hello hello.cpp,没问题。但有人写成g++ hello.cpp hello -o,编译直接报错。
2.4.2 警告选项
我最看重这个。写C++不开警告,等于裸奔。
| 选项 | 作用 |
|---|---|
-Wall |
开启大多数常见警告 |
-Wextra |
开启额外警告 |
-Werror |
把警告当作错误处理 |
-pedantic |
严格遵循C++标准 |
我的习惯:开发阶段用 -Wall -Wextra,发布前加上 -Werror。这样能逼自己把代码写干净。我曾经在一个项目里因为没开-Wall,漏掉了一个未初始化变量的警告,结果线上出了个诡异的bug,查了整整两天。
2.4.3 优化选项
优化等级决定了编译器怎么帮你提速。
| 选项 | 说明 |
|---|---|
-O0 |
不做优化,调试用 |
-O1 |
基础优化 |
-O2 |
推荐优化等级,兼顾速度与体积 |
-O3 |
激进优化,可能增加代码体积 |
-Os |
优化体积 |
为什么会这样?-O2和-O3的区别在于,-O3会启用一些循环展开、函数内联等激进优化。但有时候-O3反而会引入bug——我遇到过,一个函数在-O2下跑得好好的,换成-O3就崩了。所以发布前一定要测试。
2.4.4 调试与标准选项
| 选项 | 作用 |
|---|---|
-g |
生成调试信息,配合GDB使用 |
-std=c++11/14/17/20 |
指定C++标准版本 |
我建议新项目一律用-std=c++17或-std=c++20。老项目嘛,看情况。有些公司还在用C++11,你强行上C++20,编译不过就尴尬了。
2.5 完整编译流程
GCC/G++的编译分四步:预处理 → 编译 → 汇编 → 链接。我画了个图,帮你理解:
你想想看,平时我们敲g++ main.cpp -o main,其实背后就是这四步一气呵成。但如果你只想检查预处理结果,或者只想生成目标文件,就可以用对应的选项停下来。
2.6 实战:一个完整的编译命令
把上面学的串起来,写个正经的编译命令:
g++ -Wall -Wextra -Werror -O2 -std=c++17 -g main.cpp utils.cpp -o myapp
这条命令干了什么?
-Wall -Wextra -Werror:开启所有警告,并当作错误处理-O2:二级优化-std=c++17:使用C++17标准-g:生成调试信息main.cpp utils.cpp:两个源文件-o myapp:输出名为myapp
避坑指南:我曾经在一个项目里,把-std=c++17写成了-std=c++17(少了个等号),结果编译器报了一堆看不懂的错误。后来才发现是语法问题。嗯,这种低级错误,犯过一次就记住了。
2.7 小结
这一章我们聊了GCC/G++的安装、基本命令和常用选项。说白了,核心就三点:
- 安装:Linux用build-essential,Windows用MinGW
- 基本命令:
g++ 源文件 -o 输出文件 - 常用选项:
-Wall -O2 -std=c++17 -g这四件套,基本够用
记住,编译选项不是越多越好。够用就行。我见过有人把几十个选项堆在一起,结果编译速度慢得离谱,还容易出问题。