推荐的C语言GCC警告选项

88

相关:*C语言中有哪些有用的GCC标志?* - Peter Mortensen
15个回答

51

我经常使用:

gcc -m64 -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual \
    -Wstrict-prototypes -Wmissing-prototypes

这个设置对于不习惯它的人(第一次使用这些标志编译代码的人)很容易出现问题,但很少给我带来麻烦(尽管 -Wcast-qual 偶尔会有些麻烦)。


1
最近我发现,为了检测MSVC(基本上仍然是C89编译器)无法处理的代码,我必须添加“-Wdeclaration-after-statement”。这真是个麻烦。另外,添加“-Wextra”也可以发现一些其他问题。 - Jonathan Leffler
2
此外,添加“-O3”或类似的内容是一个好主意;只有在代码被优化时才会生成某些警告。 - Jonathan Leffler
3
根据 GCC 文档,-O2 是最容易发现警告的选项。我不确定 -O3 是否包含 -O2 或允许生成更多警告。 - Offirmo
3
如果你不在64位环境下,请跳过-m64。 - Tor Klingberg
1
使用-m32-m64(当然是在不同的运行中)可以更好地保护您免受在使用printf()scaf()转换规范时出现的各种错误的影响。 - Jonathan Leffler

47
截至2011年9月1日,使用GCC版本4.6.1
我的当前“开发”别名

gcc -std=c89 -pedantic -Wall \      -Wno-missing-braces -Wextra -Wno-missing-field-initializers \      -Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \      -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \      -Wstrict-prototypes -Winline -Wundef -Wnested-externs \      -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \      -Wfloat-equal -Wstrict-aliasing=2 -Wredundant-decls \      -Wold-style-definition -Werror \      -ggdb3 \      -O0 \      -fno-omit-frame-pointer -ffloat-store \      -fno-common -fstrict-aliasing \      -lm

该段文本为GCC编译器的一些编译选项,用于控制编译过程中的警告和错误提示等。
“发布”别名 gcc -std=c89 -pedantic -O3 -DNDEBUG -lm 截至2009年11月3日,“开发”别名
"release"别名:

gcc -Wall -Wextra -Wformat=2 -Wswitch-default -Wcast-align \      -Wpointer-arith -Wbad-function-cast -Wstrict-prototypes \      -Winline -Wundef -Wnested-externs -Wcast-qual -Wshadow \      -Wwrite-strings -Wconversion -Wunreachable-code \      -Wstrict-aliasing=2 \      -ffloat-store -fno-common -fstrict-aliasing \      -lm -std=c89 -pedantic -O3 -DNDEBUG -pg --coverage

gcc -lm -std=c89 -pedantic -O3 -DNDEBUG --combine \      -fwhole-program -funroll-loops

这是一条编译命令,意思是使用gcc编译器进行编译,并使用以下选项:链接数学库(-lm)、使用c89标准(-std=c89)、启用严格的警告(-pedantic)、开启优化等级为3(-O3)、定义NDEBUG宏(-DNDEBUG),以及可能会使用的三个链接选项:--combine、-fwhole-program和-funroll-loops。

1
“-Wfloat-equal” 已添加到我的别名中。谢谢 Mark。 - pmg
5
请注意,使用最新版的gcc编译器时,-Wstrict-aliasing=2实际上会降低由-Wall隐含的-Wstrict-aliasing=3警告级别。 - nwellnhof
@nwellnhof 这就是自定义警告设置的关键,它们会随着时间的推移而变得陈旧... - yugr
自GCC 4.6以来,-Wunreachable-code已被列为虚拟开关(GCC 4.6.0发布于2011年3月25日)。一个回答声称*“-Wunreachable-code一直是有问题的” *。 - Peter Mortensen
-combine was removed in GCC 4.6.0 (released 2011-03-25): "The C-only intermodule optimization framework (IMA, enabled by -combine) has been removed in favor of the new generic link-time optimization framework (LTO) introduced in GCC 4.5.0.". The last version was 4.5.4. It is listed as -combine, not --combine - Peter Mortensen

17

我最开始学习的是C++,所以当我转而学习C语言时,我确保自己更加谨慎:


6
你可以同时使用-ansi,-pedantic和-std=c99吗?-ansi不是与c89几乎相同的东西吗?如果是,那么如何与c99标志一起使用? - Johan
2
@Johan - 你可以这样做,但实际上并不是必须的,因为我最近发现-ansi隐含了-std=<default>,所以你只需要说-std=c99 -pedantic就可以达到完全相同的效果。但我通常还是会使用它,只是出于文档记录的目的。我觉得它读起来是,“这段代码符合ANSI标准(严格!),使用标准C99。”紧接着通常是-Wno-long-long或类似的内容,即任何与ANSI标准有关的例外。 - Tom
1
你不是忘了加上-pedantic-errors吗?它和-Werror=pedantic不一样。 - x-yuri
1
正如在其他答案的评论中提到的,-Wstrict-aliasing现在已经成为-Wall的一部分。 - yugr

15

我喜欢使用-Werror选项。它可以保持代码无警告。


21
如果没有-Werror,所有其他警告选项都毫无意义。将警告视为错误几乎是确保解决警告的唯一方法。如果它们只是警告,开发人员可能会决定保留其中一个,因为他确信它是无效的。这甚至可能是真的,但下一个开发人员却不会修复他引入的警告,因为他在所有其他警告之间没有看到它,或者因为它只是又一个警告。 - Kristof Provost
7
我不同意Kristof的观点,因为很多时候,我更愿意先编译一个可用的副本,然后再解决错误。 - Yktula
9
我理解这种想法的诱惑,但是一旦你有一个可行的版本,你更有可能因为“它可用”而不去改变它。在企业环境中这种风险甚至更高,因为你需要说服老板留给你时间去修复警告。 - JesperE
2
我认为摆脱#warning是使用-Werror的一个好的副作用。 - JesperE
5
如果你在开源项目上工作,请不要默认使用 -Werror 进行构建,这会令使用不同编译器版本的打包者感到困扰,因为警告有时会随着编译器版本的变化而改变,有些对你而言无警告的代码可能会对其他人产生警告,然后他们就必须深入你的构建系统来关闭它。 - Spudd86
显示剩余4条评论

10

获取您使用的GCC版本的手册,找到所有可用的警告选项,然后仅停用那些您有强烈理由停用的选项。(例如,无法修改的第三方头文件,在其他情况下会给您带来大量警告。)记录下这些理由。(在Makefile或设置这些选项的任何地方。)定期检查设置,以及每次升级编译器时。

编译器是您的朋友,警告也是您的朋友。尽可能让编译器向您报告可能存在的问题。


3
FYI,该手册没有提供一个单一的全面的警告列表。但是,您可以在此处找到这样的列表 here,以及用于生成它们的工具。 - Kyle Strand

6
我还使用:

-Wstrict-overflow=5

为了捕获那些可能会发生的错误,如果我编写依赖于整数溢出行为的代码。
并且:

-Wextra

这使一些不错的选项得以启用。虽然大多数是针对C++的。

4
-Wextra 似乎是 -W 的新名称 (-W 仍然被支持)。 - Sard

2
我通常使用 "-W -Wall -ansi -pedantic" 进行编译。
这有助于确保代码的最大质量和可移植性。

3
注意:-ansi会覆盖 -std=c99。意思是使用-ansi选项时,会优先采用符合ANSI C标准的语法规则,而不是C99标准的语法规则。 - Sard
2
“-ansi”不就等同于使用“-std=c89”吗? - helpermethod

2

3
由于工具链可以将字符串字面量放入只读内存,因此请注意。 - DevSolar
3
为什么要使用-Wno-unused-parameter?很少情况下它指向真正的问题(而“很少情况下”是禁用它的确切危险:难以发现的错误是最难以检测的)。例如,它可能会在Foo(int dndu, int dndv):dndu_(dndu),dndv_(dndu){}触发->相对难以发现。如果你对这个警告感到烦恼,你应该将参数foo (int /*q*/)注释掉,这也提高了你代码的可读性。 - Sebastian Mach
在重构过程中,我有时会错误地使用本地变量来遮盖参数,这也有助于捕获这种情况。 - paulm

2

2
使用了-Wconversion选项后,我花了几个小时测试代码中的各种数据类型并进行重新编译,之后我对-Wconversion进行了研究,并不建议在一般情况下使用它。问题在于它会针对如下代码生成警告:char a = 5; char b = a - 1;这是在使用gcc 4.3.2 (Debian 4.3.2.-1.1)时出现的。 - James Morris
1
-Wconversion警告可以通过以下方法消除(例如在上面的注释中):char a = 5; char b = (char)(a - 1); 注意括号。 - James Morris
-Wconversion可能在以下情况下引起问题:struct data_t {u16 a:11, b:11, ...}; data_t v; v.a = u16(1024); v.b = u16(512); 我看不到任何方法可以在这里进行适当的"转换"。只是一个范围检查。 - undefined

1

我通常只使用

gcc -Wall -W -Wunused-parameter -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -Wsign-compare -Wconversion -Wshadow -Wcast-align -Wparentheses -Wsequence-point -Wdeclaration-after-statement -Wundef -Wpointer-arith -Wnested-externs -Wredundant-decls -Werror -Wdisabled-optimization -pedantic -funit-at-a-time -o

参考资料:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接