> 原文
Codeforces
By andreyv
不完全翻译原文,但是大多数内容来自原文
对于大多数 OIer,GCC/G++ 编译选项是比较常用的,比如 -O2
开启 O2 优化、-Wl,--stack=xxx
扩栈之类的……
但是 GCC 编译器有一个缺陷,它默认“所有程序员编写的代码都是正确的”。事实上,一些不经意犯的小错误常常会让我们花费很久的时间调试。
Part1. 初识 -Wall
对于这一点,GCC开发者写了这样一个编译选项 —— 经常会用到的编译选项 -Wall
,是我觉得最好用的编译选项!它可以分析一些可能错误的代码,并给出 [Warning]
提示,比如:
1 | long long a=1ll<<60; |
这个程序如果不开 -Wall
,编译器并不会报错,然而显然是不符合我们的意思的。如果开了 -Wall
,编译信息中就会出现:
[Warning] format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long long int’ [-Wformat=]
这只是 -Wall
的一个功能,它还能检测:
scanf/printf
中参数与占位符数量不等:1
2
3
4
5printf("%d",1,2);
/*
显示:
[Warning] too many arguments for format [-Wformat-extra-args]
*/没有使用的局部变量(如果你定义了一个局部变量,但是从来没有使用),显示
1
[Warning] unused variable 'b' [-Wunused-variable]
调用未赋值的局部变量,显示
1
[Warning] 'a' is used uninitialized in this function [-Wuninitialized]
调用了变量但是没有进行操作(有时候zz就忘了打运算符)比如想打
cnt++;
,然后只写了cnt;
会显示:1
[Warning] statement has no effect [-Wunused-value]
好像还有一些奇怪的东西……
Part2. 深入了解 GCC 编译警告
以下内容多来自原文,有删改
-pedantic -std=...
,随着 C++ 的不断翻新,C++98 到 C++17 的差别是非常大的;为了增强不同版本的兼容性,有一些较新版本的写法在旧版本上编译也会判为正确。但是考试的时候,编译一般是比较严格的,就可能发生 CE 的惨案……
有了这行命令会发生什么?比如下面这种写法在 C++11 及以上的版本是支持的,但是 C++98 并不支持,但是编译器并不认为错误:
1
2
3
4
5
6
7
using namespace std;
struct NODE{int x;}n;
int main(){
n=(NODE){1};
return 0;
}如果加上
-pedantic -std=c++98
,就会警告:1
[Warning] ISO C++ forbids compound-literals [-Wpedantic]
-Wshadow
,也是非常有用了 —— 用于警告变量重名,比如:1
2
3
4int n;
int main(){
int n=1;
}会警告:
1
[Warning] declaration of 'n' shadows a global declaration [-Wshadow]
-Wfloat-equal
,C++ 的double
有精度误差,因此很少会用a==b
来判断两个 double 变量相等,而是用ABS(a-b)<EPS
。加上这条命令,如果你用了==
判断 double 变量相等,会警告:1
[Warning] comparing floating point with == or != is unsafe [-Wfloat-equal]
-Wconversion
,警告运算过程中变量的类型转换,这些运算往往是隐性的 —— 比如一个long long
乘上int
,int
会被转成long long
。然而这些转换是我们不知道的,加上这条命令可以让它显示出来,比如:1
2long long a=1ll<<40;
int x=a*23;警告:
1
[Warning] conversion to 'int' from 'long long int' may alter its value [-Wconversion]
以上就是在 OI 中比较常用的,那些难记住的或与 OI 无关的就没有再搬运了;
reader 们可以在文章顶部找到原文的超链接,顺便在 Codeforces 上给原博主点个赞~