g++ 命令详解与参数实测(Ubuntu 22.04)
g++ 命令逐参数实测:一步编译与 -o、类工程 -c 多文件链接、-std=c++98~c++23 标准矩阵与 __cplusplus 实值、模板与 STL、-Wall/-Wextra/-Wshadow/-Werror 警告矩阵、-O0~-O3 优化与 -g/-s 体积对照、-I/-isystem/-H/-MMD 头文件工具链、-L/-l 链接顺序、-static-libstdc++、-fPIC -shared 动态库、concepts/结构化绑定标准门槛、-D/-dM 宏与彩色诊断,全部回显在 Ubuntu 22.04(g++ 11.4.0)实测通过。
g++ 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 g++ 的每一个常用参数——一步编译与
-o、类工程多文件-c链接、-std=c++98~c++23标准矩阵与__cplusplus实值、模板与 STL 编译、警告矩阵-Wall/-Wextra/-Wpedantic/-Wshadow/-Werror、优化-O0~-O3/-Os/-Og与-g/-s、头文件-I/-isystem/-H/-MMD、库链接-L/-l/-static-libstdc++、动态库-fPIC -shared、-static全静态、现代特性 concepts/结构化绑定、宏-D/-dM与诊断控制,全部命令与回显已在 Ubuntu 22.04(g++ 11.4.0)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64),root 身份执行
- g++ 版本:11.4.0(
g++ --version实测:g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0) - 与 gcc 11.4.0、GNU Make 4.3、cmake 3.22.1 同属 build-essential 工具链
- 链接关系实测:
/usr/bin/g++ -> g++-11 -> x86_64-linux-gnu-g++-11;/usr/bin/c++ -> /etc/alternatives/c++ - C++ 头文件搜索链首四项实测:
/usr/include/c++/11、/usr/include/x86_64-linux-gnu/c++/11、/usr/include/c++/11/backward、/usr/lib/gcc/x86_64-linux-gnu/11/include - 默认语言标准:
gnu++17(__cplusplus实测 201703)
💡 技术拓展:g++ 与 gcc 是同一套 GCC 前端驱动的两个入口,三点差异——g++ 把
.c之外的后缀按 C++ 编译、自动链接 libstdc++、对 C++ 专属诊断(如模板报错)提供更完整支持。gcc file.cpp虽也能编译 C++ 语法,但链接阶段缺 libstdc++ 会报 undefined reference。库分发时还常遇到-static-libstdc++(把 C++ 运行库静态打入,产物可在无对应版本 libstdc++ 的机器上运行)。
二、命令概览
2.1 环境速览
$ g++ --version
g++ (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.
$ g++ -dumpversion
11
$ g++ -dumpfullversion
11.4.0
$ g++ -dumpmachine
x86_64-linux-gnu
$ command -v g++
/usr/bin/g++
$ ls -l /usr/bin/g++ /usr/bin/c++
lrwxrwxrwx 1 root root 21 Oct 17 02:00 /usr/bin/c++ -> /etc/alternatives/c++
lrwxrwxrwx 1 root root 6 Aug 5 2021 /usr/bin/g++ -> g++-11
$ ls -l /usr/bin/x86_64-linux-gnu-g++ /usr/bin/g++-11
lrwxrwxrwx 1 root root 23 Dec 18 2025 /usr/bin/g++-11 -> x86_64-linux-gnu-g++-11
lrwxrwxrwx 1 root root 6 Aug 5 2021 /usr/bin/x86_64-linux-gnu-g++ -> g++-11
$ dpkg -l | grep -E "^ii +(g\+\+|gcc-11) "
ii g++ 4:11.2.0-1ubuntu1 amd64 GNU C++ compiler
ii gcc-11 11.4.0-1ubuntu1~22.04.3 amd64 GNU C compiler
$ g++ -print-search-dirs | head -3
install: /usr/lib/gcc/x86_64-linux-gnu/11/
programs: =/usr/lib/gcc/x86_64-linux-gnu/11/:...
libraries: =/usr/lib/gcc/x86_64-linux-gnu/11/:...
$ g++ -v -E -x c++ /dev/null -o /dev/null 2>&1 | sed -n "/search starts here:/,/End of search/p"
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/11
/usr/include/x86_64-linux-gnu/c++/11
/usr/include/c++/11/backward
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
2.2 --help 与分类帮助
$ g++ --help | head -12
Usage: g++ [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|...}.
Display specific types of command line options.
(Use '-v --help' to display command line options of sub-processes).
--version Display compiler version information.
...
$ g++ --help | wc -l
61
$ g++ --help=common | head -8
The following options are language-independent:
--completion= Provide bash completion for options starting with
provided string.
--debug Same as -g.
...
$ g++ --target-help 2>&1 | head -5
The following options are target specific:
-m128bit-long-double sizeof(long double) is 16.
-m16 Generate 16bit i386 code.
-m32 Generate 32bit i386 code.
--help=common|optimizers|warnings|target 可分类拉取选项清单,全量选项远多于顶层 --help 的 61 行。
三、基础编译:一步到位与 -o
$ cat hello.cpp
#include <iostream>
int main()
{
std::cout << "hello, g++!" << std::endl;
return 0;
}
$ g++ hello.cpp # 默认输出 a.out
$ ls -l a.out
-rwxr-xr-x 1 root root 16808 Oct 17 02:14 a.out
$ ./a.out
hello, g++!
$ g++ hello.cpp -o hello
$ ./hello
hello, g++!
$ g++ hello.cpp -o /tmp/gxxdemo/basic/hello2 # -o 支持绝对路径
$ ls -l /tmp/gxxdemo/basic/hello2
-rwxr-xr-x 1 root root 16808 Oct 17 02:14 /tmp/gxxdemo/basic/hello2
$ g++ -v hello.cpp -o hello3 2>&1 | tail -4
/usr/lib/gcc/x86_64-linux-gnu/11/collect2 ... -o hello3 ...
COLLECT_GCC_OPTIONS='-v' '-o' 'hello3' '-mtune=generic' '-march=x86-64' '-dumpdir' 'hello3.'
同一源码,g++ 产物(16808 字节)比 gcc 的 C 版(15960)略大——libstdc++ 的 iostream 启动骨架。
四、-c 与多文件类工程
$ cat counter.h
#ifndef COUNTER_H
#define COUNTER_H
#include <string>
class Counter
{
public:
explicit Counter(std::string name);
void incr();
int value() const;
const std::string &name() const;
private:
std::string name_;
int count_ = 0;
};
#endif
$ g++ -c counter.cpp # 只编译不链接 → counter.o
$ g++ -c main.cpp # → main.o
$ g++ -c main.cpp -o main_obj.o
$ ls -l *.o
-rw-r--r-- 1 root root 2832 Oct 17 02:14 counter.o
-rw-r--r-- 1 root root 2456 Oct 17 02:14 main.o
-rw-r--r-- 1 root root 2456 Oct 17 02:14 main_obj.o
$ g++ main.o counter.o -o app
$ ./app
demo = 3
$ g++ main.cpp counter.cpp -o app_all # 一步到位
$ ./app_all
demo = 3
$ g++ -c counter.cpp main.cpp # -c 一次接多个源文件
$ g++ main.o -o app_bad # 少链接 counter.o
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x2e): undefined reference to `Counter::incr()'
/usr/bin/ld: main.cpp:(.text+0x45): undefined reference to `Counter::value()'
collect2: error: ld returned 1 exit status
C++ 的 undefined reference 报错会以修饰名(mangled name,如 Counter::incr())显示,可直接定位类与成员函数。
五、-std 标准矩阵与 __cplusplus
$ cat std.cpp
#include <cstdio>
int main()
{
printf("__cplusplus = %ld\n", __cplusplus);
return 0;
}
$ g++ -std=c++98 std.cpp -o s98 && ./s98
__cplusplus = 199711
$ g++ -std=c++11 std.cpp -o s11 && ./s11
__cplusplus = 201103
$ g++ -std=c++14 std.cpp -o s14 && ./s14
__cplusplus = 201402
$ g++ -std=c++17 std.cpp -o s17 && ./s17
__cplusplus = 201703
$ g++ -std=c++20 std.cpp -o s20 && ./s20
__cplusplus = 202002
$ g++ -std=c++23 std.cpp -o s23 && ./s23
__cplusplus = 202100
$ g++ std.cpp -o sdefault && ./sdefault # 不加 -std
__cplusplus = 201703 # 默认 gnu++17
$ g++ -std=gnu++17 std.cpp -o g17 && ./g17
__cplusplus = 201703
$ g++ -std=c++2a std.cpp -o s2a && ./s2a # c++2a 是 c++20 的旧拼写,仍兼容
__cplusplus = 202002
新特性代码在不同标准下的行为对照:
$ cat feature.cpp
#include <cstdio>
int main()
{
auto x = 42; /* C++11 起 */
printf("%d\n", x);
return 0;
}
$ g++ -std=c++98 feature.cpp -o f98
feature.cpp:5:10: error: 'x' does not name a type
5 | auto x = 42;
| ^
$ g++ -std=c++11 feature.cpp -o f11 && ./f11
42
| -std 取值 | 含义 | __cplusplus 实测 |
|---|---|---|
| c++98 | ISO C++98 | 199711 |
| c++11 | ISO C++11 | 201103 |
| c++14 | ISO C++14 | 201402 |
| c++17 / c++2a | ISO C++17 / 20 旧拼法 | 201703 / 202002 |
| c++20 | ISO C++20 | 202002 |
| c++23 | ISO C++23(实验性) | 202100 |
| (默认)/ gnu++17 | GNU 扩展版 C++17 | 201703 |
六、模板与 STL 工程
$ cat maxval.hpp
#ifndef MAXVAL_HPP
#define MAXVAL_HPP
template <typename T>
const T &maxval(const T &a, const T &b)
{
return a < b ? b : a;
}
#endif
$ cat main.cpp
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include "maxval.hpp"
int main()
{
std::vector<int> v{3, 1, 4, 1, 5, 9, 2, 6};
std::map<std::string, int> ages{{"alice", 30}, {"bob", 25}};
std::cout << "max=" << maxval(3, 9) << '\n';
for (const auto &[name, age] : ages)
std::cout << name << ":" << age << ' ';
std::cout << '\n';
return 0;
}
$ g++ -std=c++17 main.cpp -o app
$ ./app
max=9
alice:30 bob:25
$ g++ -std=c++17 -O2 main.cpp -o app_o2 && ./app_o2
max=9
alice:30 bob:25
$ g++ -std=c++98 main.cpp -o app98
main.cpp:9:22: error: in C++98 'v' must be initialized by constructor, not by '{...}'
main.cpp:12:21: error: expected '[' before '&' token # 结构化绑定是 C++17 特性
12 | for (const auto &[name, age] : ages)
$ g++ -std=c++11 main.cpp -o app11
main.cpp:12:22: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
模板函数必须放头文件(实例化点需要完整定义);列表初始化与结构化绑定分别受 C++11/C++17 门槛限制,错误信息会给出"only available with ..."提示。
七、警告矩阵:-Wall / -Wextra / -Wpedantic / -Wshadow / -Werror
int unused_var = 7; // 未使用
int x = 1;
{
double x = 3.14; // 遮蔽外层 x
}
if (x = 2) // 条件里赋值
char c = 300; // 溢出窄化
实测各开关命中的警告:
$ g++ warn.cpp -o w1
warn.cpp:13:14: warning: overflow in conversion from 'int' to 'char' ... [-Woverflow]
$ g++ -Wall warn.cpp -o w2
warn.cpp:11:11: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
warn.cpp:13:14: warning: overflow in conversion from 'int' to 'char' ... [-Woverflow]
warn.cpp:5:9: warning: unused variable 'unused_var' [-Wunused-variable]
$ g++ -Wall -Wextra warn.cpp -o w3 # 与 -Wall 相同(本例无参数类问题)
$ g++ -Wall -Wextra -Wpedantic warn.cpp -o w4 # 严格 ISO 检查,多出扩展语法告警
$ g++ -Wall -Wextra -Wshadow warn.cpp -o w5
warn.cpp:7:16: warning: declaration of 'x' shadows a previous local [-Wshadow]
7 | double x = 3.14;
$ g++ -Wall -Wextra -Werror warn.cpp -o w6
warn.cpp:11:11: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
...
$ g++ -w warn.cpp -o w7 # -w 全静默
要点:变量遮蔽(shadow)必须显式加 -Wshadow,其余常用项 -Wall 基本覆盖;CI 建议统一 -Wall -Wextra -Wshadow -Werror。
八、优化等级与体积控制
STL 密集代码(vector + string)在六档优化下的实测:
$ g++ -O0 heavy.cpp -o h_O0
$ g++ -O1 heavy.cpp -o h_O1
$ g++ -O2 heavy.cpp -o h_O2
$ g++ -O3 heavy.cpp -o h_O3
$ g++ -Os heavy.cpp -o h_Os
$ g++ -Og -g heavy.cpp -o h_Og
$ ls -l h_O0 h_O1 h_O2 h_O3 h_Os h_Og
-rwxr-xr-x 1 root root 27128 Oct 17 02:50 h_O0
-rwxr-xr-x 1 root root 16816 Oct 17 02:50 h_O1
-rwxr-xr-x 1 root root 16896 Oct 17 02:50 h_O2
-rwxr-xr-x 1 root root 16784 Oct 17 02:50 h_O3
-rwxr-xr-x 1 root root 109648 Oct 17 02:50 h_Og # -Og -g 带全量调试信息
-rwxr-xr-x 1 root root 17128 Oct 17 02:50 h_Os
$ ./h_O0 && ./h_O3 # 两次输出一致,优化不改变语义
332833500 333283335000
$ g++ -O2 -g heavy.cpp -o h_g && ls -l h_O2 h_g
-rwxr-xr-x 1 root root 16896 Oct 17 02:50 h_O2
-rwxr-xr-x 1 root root 110000 Oct 17 02:50 h_g # -g 附带 DWARF
$ g++ -O2 -s heavy.cpp -o h_s && ls -l h_O2 h_s
-rwxr-xr-x 1 root root 16896 Oct 17 02:50 h_O2
-rwxr-xr-x 1 root root 14568 Oct 17 02:50 h_s # -s 剥离符号表
$ g++ -O2 -march=native heavy.cpp -o h_native && ./h_native
332833500 333283335000
C++ 代码 -O0 与 -O1 体积差 10KB(iostream 内联展开策略不同);-O3 未必比 -O2 大(模板实例去重);调试信息让体积翻 6 倍。
九、头文件搜索:-I / -isystem / -H / -MM
$ mkdir -p incs && cat > incs/myutil.hpp
#pragma once
namespace myutil
{
inline int twice(int x) { return 2 * x; }
}
$ g++ main.cpp -o a1
main.cpp:2:10: fatal error: myutil.hpp: No such file or directory
2 | #include <myutil.hpp>
$ g++ -Iincs main.cpp -o a2 && ./a2 # -I 紧贴路径(最常用写法)
42
$ g++ -I incs main.cpp -o a3 && ./a3 # -I 与路径分离亦可
42
$ g++ -isystem incs main.cpp -o a4 && ./a4 # 标记为系统目录,抑制其中警告
42
$ g++ -Iincs -H main.cpp -o a5 2>&1 | head -6 # -H 逐层展示头文件包含树
. /usr/include/c++/11/iostream
.. /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h
... /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h
.... /usr/include/features.h
..... /usr/include/features-time64.h
...... /usr/include/x86_64-linux-gnu/bits/wordsize.h
$ g++ -Iincs -MM main.cpp # 生成 Make 依赖规则
main.o: main.cpp incs/myutil.hpp
$ g++ -Iincs -MMD main.cpp -o a6 && cat a6.d
a6: main.cpp incs/myutil.hpp
⚠️
-MMD的产物名跟随-o输出名(这里是a6.d),不叫main.d——写 Makefile 的%.d: %.cpp规则时要用$(*:.o=.d)类的推导,别硬编码源文件名。
十、库链接:-L / -l / -static-libstdc++
$ g++ -c mymath.cpp && ar rcs libmylib.a mymath.o
$ g++ main.cpp -lmylib -o bad_noflag # 不加 -L 找不到当前目录的库
/usr/bin/ld: cannot find -lmylib
$ g++ main.cpp -L. -lmylib -o app
$ ./app
area=12.5664
$ g++ -L. -lmylib main.cpp -o bad_order # 库写在源文件之前
/usr/bin/ld: main.cpp:(.text+0x2e): undefined reference to `mymath::circle_area(double)'
$ g++ main.cpp -L. -lmylib -static-libstdc++ -static-libgcc -o app_static
$ ./app_static
area=12.5664
$ ldd app | grep -E "stdc|gcc"
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007b584e173000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007b584de43000)
$ ldd app_static | grep -cE "stdc|gcc_s"
0
-static-libstdc++ -static-libgcc 把 C++/GCC 运行库静态打入(libstdc++.so.6 从依赖表消失),产物可分发到没有对应运行库版本的目标机;业务代码仍默认动态。注意 libstdc++ 默认是动态链接的,且链接顺序规则与 gcc 相同(被依赖库放后)。
十一、动态库:-fPIC -shared 与运行期路径
$ g++ -fPIC -c mymath.cpp -o mymath_pic.o
$ g++ -shared mymath_pic.o -o libmymath.so
$ ls -l libmymath.so
-rwxr-xr-x 1 root root 15232 Oct 17 02:50 libmymath.so
$ g++ main.cpp -L. -lmymath -o app_so
$ ldd app_so | grep mymath
libmymath.so => not found
$ ./app_so
./app_so: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory
$ LD_LIBRARY_PATH=. ./app_so
area=12.5664
$ g++ main.cpp ./libmymath.so -o app_so2 # 直接把 .so 路径当输入,链接期记录绝对/相对路径
$ ldd app_so2 | grep mymath
./libmymath.so (0x00007fc2b6cf3000)
$ LD_LIBRARY_PATH=. ./app_so2
area=12.5664
$ g++ -fPIC -shared mymath.cpp -o libmymath2.so # 一步法:-fPIC -shared 直接接源文件
$ ls -l libmymath2.so
-rwxr-xr-x 1 root root 15232 Oct 17 02:50 libmymath2.so
十二、-static 全静态
$ g++ main.cpp -L. -lmymath -o app_a # 默认动态
$ g++ main.cpp -L. -lmymath -static-libstdc++ -static-libgcc -o app_sl
$ g++ main.cpp -L. -lmymath -static -o app_st # 全静态
$ ls -l app_a app_sl app_st
-rwxr-xr-x 1 root root 16600 Oct 17 02:50 app_a
-rwxr-xr-x 1 root root 1370784 Oct 17 02:50 app_sl
-rwxr-xr-x 1 root root 2404064 Oct 17 02:50 app_st
$ ldd app_a | grep -E "stdc|gcc_s"
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007b584e173000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007b584de43000)
$ ldd app_sl | grep -cE "stdc|gcc_s"
0
$ ldd app_st
not a dynamic executable
$ ./app_st
area=12.5664
三档体积:动态 16KB → 运行库静态 1.3MB → 全静态 2.4MB。
十三、现代 C++ 特性与标准门槛
$ cat mod17.cpp
#include <iostream>
#include <map>
#include <string>
int main()
{
auto add = [](auto a, auto b) { return a + b; }; // 泛型 lambda(C++14)
std::map<std::string, int> m{{"k", 1}, {"j", 2}};
for (const auto &[key, val] : m) // 结构化绑定(C++17)
std::cout << key << '=' << val << ' ';
std::cout << "| add(1,2.5)=" << add(1, 2.5) << '\n';
constexpr int n = 5;
static_assert(n == 5, "n must be 5");
return 0;
}
$ g++ -std=c++17 mod17.cpp -o m17 && ./m17
j=2 k=1 | add(1,2.5)=3.5
$ g++ -std=c++11 mod17.cpp -o m11
mod17.cpp:9:22: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
$ cat mod20.cpp
#include <iostream>
#include <type_traits>
#include <vector>
template <typename T>
concept Numeric = std::is_arithmetic_v<T>; // concepts(C++20)
template <Numeric T>
T twice(T x) { return x * 2; }
int main()
{
std::cout << twice(21) << ' ' << twice(2.5) << '\n';
std::vector v{1, 2, 3}; // CTAD 类模板实参推导
for (auto x : v)
std::cout << x << ' ';
std::cout << '\n';
return 0;
}
$ g++ -std=c++20 mod20.cpp -o m20 && ./m20
42 5
1 2 3
$ g++ -std=c++17 mod20.cpp -o m20b
mod20.cpp:5:1: error: 'concept' only available with '-std=c++20' or '-std=gnu++20'
5 | concept Numeric = std::is_arithmetic_v<T>;
map 输出 j=2 k=1(按 key 字典序)再次印证关联式序列的标准行为;concepts 需要 -std=c++20,错误提示会直接给出可用标准。
十四、宏定义:-D / -U / -dM
$ cat macro.cpp
#include <iostream>
int main()
{
#ifdef VERSION_NAME
std::cout << "build: " << VERSION_NAME << '\n';
#else
std::cout << "build: unknown\n";
#endif
#ifdef DEBUG_LEVEL
std::cout << "debug=" << DEBUG_LEVEL << '\n';
#endif
std::cout << "cplusplus=" << __cplusplus << " gnu=" << __GNUC__ << '\n';
return 0;
}
$ g++ macro.cpp -o m1 && ./m1
build: unknown
cplusplus=201703 gnu=11
$ g++ -DVERSION_NAME='"v1.0.0"' macro.cpp -o m2 && ./m2
build: v1.0.0
$ g++ -DDEBUG_LEVEL=2 macro.cpp -o m3 && ./m3
build: unknown
debug=2
$ g++ -DDEBUG_LEVEL=2 -UDEBUG_LEVEL macro.cpp -o m4 && ./m4 # -U 反向取消
build: unknown
cplusplus=201703 gnu=11
$ echo | g++ -dM -E -x c++ - | grep -E " __cplusplus| __GNUC__ | __linux | __x86_64"
#define __cplusplus 201703L
#define __GNUC__ 11
#define __linux 1
#define __x86_64 1
十五、编译阶段拆分与产物命名
$ g++ -E stage.cpp -o stage.i && ls -l stage.i
-rw-r--r-- 1 root root 778397 Oct 17 02:50 stage.i # iostream 展开后 77 万字符
$ grep -c "" stage.i
32261
$ grep GREET stage.i # 宏已替换,无残留
$ g++ -S stage.cpp -o stage.s && head -8 stage.s
.file "stage.cpp"
.text
.local _ZStL8__ioinit # 修饰名
.comm _ZStL8__ioinit,1,1
.section .rodata
.LC0:
.string "hi"
$ g++ -c stage.cpp -o stage.o
$ g++ stage.o -o stage_bin && ./stage_bin
hi, g++
$ g++ -save-temps stage.cpp -o st && ls st* # gcc 11 产物命名
st st-stage.ii st-stage.o st-stage.s
$ head -3 st-stage.ii
# 1 "stage.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
⚠️ gcc 11 的
-save-temps产物为<output>-<source基名>格式(st-stage.ii/.o/.s),不是老文档写的st.ii;C++ 预处理产物后缀是.ii。
十六、错误诊断与颜色控制
$ cat syntax.cpp
#include <iostream>
int main()
{
std::cout << "missing semicolon"
return 0;
}
$ g++ syntax.cpp -o s1
syntax.cpp: In function 'int main()':
syntax.cpp:5:32: error: expected ';' before 'return'
5 | std::cout << "missing semicolon"
| ^
| ;
$ g++ -fmax-errors=3 syntax.cpp -o s2 # 限制最多报 3 条错误
$ g++ -fdiagnostics-color=always syntax.cpp -o s3 2>&1 | head -6 | cat -v
syntax.cpp: In function 'int main()':
syntax.cpp:5:32: error: expected ^[[01m^[[K';'^[[m^[[K before ^[[01m^[[K'return'^[[m^[[K
5 | std::cout << "missing semicolon" # ^[[01m 等为 ANSI 颜色码
| ^[[01m^[[K^[[m^[[K^[[01m^[[K;
...
$ cat ref.cpp
extern void not_defined(int);
int main()
{
not_defined(1);
return 0;
}
$ g++ ref.cpp -o r1
/usr/bin/ld: /tmp/ccG9oQ3t.o: in function `main':
ref.cpp:(.text+0x16): undefined reference to `not_defined(int)'
collect2: error: ld returned 1 exit status
$ g++ -w syntax.cpp -o w1 # -w 静默后错误仍会报(只压警告,不压错误)
| 报错关键行 | 阶段 | 处置 |
|---|---|---|
error: expected ';' / does not name a type | 编译期 | 源码语法 |
'concept' only available with '-std=c++20' | 编译期 | 升 -std |
fatal error: xxx.hpp: No such file or directory | 预处理期 | -I 或装 dev 包 |
undefined reference to 'Class::method()' | 链接期 | 补 .o/库、修链接顺序 |
cannot find -lxxx | 链接期 | 补 -L |
error while loading shared libraries | 运行期 | LD_LIBRARY_PATH/rpath |
structured bindings only available with -std=c++17 | 警告 | 升标准 |
十七、参数速查表
| 参数 | 作用 | 实测要点 |
|---|---|---|
-o <file> | 输出名 | 默认 a.out |
-c | 只编译不链接 | 产出 .o;缺链接报 mangled 名 |
-E / -S | 预处理 / 汇编 | .i(C++ 为 .ii)/ .s |
-save-temps | 保留中间产物 | gcc 11 命名为 out-src.ii/.o/.s |
-std=c++98~c++23 | 语言标准 | 默认 gnu++17;c++2a=c++20 |
-Wall -Wextra | 警告包 | -Wshadow 需显式加 |
-Wpedantic | 严格 ISO 告警 | 报扩展语法 |
-Werror / -w | 警告升级 / 静默 | 不影响真正的 error |
-O0~-O3 / -Os / -Og | 优化档 | STL 码 O0 27KB → O1 17KB |
-g / -s | 加调试信息 / 剥符号 | 110KB / 14.5KB 对照 |
-march=native | 按本机 CPU 生成 | 产物不可跨机型 |
-I<dir> / -isystem | 头文件目录 / 系统级 | -isystem 抑制其中警告 |
-H | 打印包含树 | 层级前缀 . .. |
-MM / -MMD | 生成 Make 依赖 | .d 名跟随 -o 输出名 |
-L<dir> / -l<name> | 库路径 / 库名 | 被依赖库放后 |
-static-libstdc++ -static-libgcc | 运行库静态 | ldd 不再显示 libstdc++ |
-fPIC -shared | 动态库 | 可一步 g++ -fPIC -shared src |
-static | 全静态 | 16KB→2.4MB 对照 |
-D<name>=<val> / -U<name> | 定义 / 取消宏 | 字符串值 '"v1.0.0"' |
-dM -E -x c++ | 导出预定义宏 | 含 __cplusplus |
-fmax-errors=N | 限制报错条数 | 大模板排错友好 |
-fdiagnostics-color=always | 强制彩色诊断 | 日志系统需配套终端解释 |
--help=common | 分类选项清单 | common/optimizers/warnings/target |
关联阅读:gcc(C 编译驱动,管线与库链接同源)、make(增量构建编排)、cmake(构建系统生成器,CXX_STANDARD/CMAKE_BUILD_TYPE 的底层就是本文的 -std 与 -O)见本专栏姊妹篇。