-Wextra
和 -Wall
: 必需的。-Wfloat-equal
: 通常测试浮点数相等性是不好的,因此这个选项很有用。-Wundef
: 如果一个未初始化的标识符在 #if
指令中被评估,警告。-Wshadow
: 当局部变量与另一个局部变量、参数或全局变量重名时,或者当一个内置函数被重名时,警告。-Wpointer-arith
: 如果任何东西依赖于函数或 void 的大小,则警告。-Wcast-align
: 当一个指针被转换为使目标所需的对齐方式增加时,警告。例如,在只能按两个或四个字节边界访问整数的机器上,如果将 char *
转换为 int *
,则发出警告。-Wstrict-prototypes
: 如果函数没有指定参数类型,则警告其声明或定义。-Wstrict-overflow=5
: 当编译器基于有符号溢出不会发生的假设进行优化时,警告该情况。 (值5可能太严格,请参阅手册页面。)-Wwrite-strings
: 把字符串常量的类型设置为const char[
length]
,这样将其地址复制到非const char *
指针中会得到警告。-Waggregate-return
: 如果定义或调用了返回结构体或联合体的函数,则发出警告。-Wcast-qual
: 每当一个指针被转换以从目标类型中删除类型限定符时,发出警告*。-Wswitch-default
: 每当switch
语句没有default
情况时,发出警告*。-Wswitch-enum
: 每当一个switch
语句具有枚举类型的索引并缺少该枚举的一个或多个命名代码的case
时,发出警告*。-Wconversion
: 警告可能改变值的隐式转换*。-Wunreachable-code
:如果编译器检测到代码永远不会被执行,则发出警告*。那些带有*标记有时会给出太多的误报警告,因此我只在需要时使用它们。
-Wformat=2
:在printf/scanf函数上进行额外的格式检查。 - schot-Wall
隐含了吗? - chacham15-Wwrite-strings
,因为我非常讨厌它。 - chacham15-Wwrite-strings
的描述明确说明它不是-Wall
的一部分:http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wwrite_002dstrings-415。也许你的设置中有其他东西设置了该标志?或者你正在编译C++? - Alok Singhal-f
代码生成选项中的几个选项比较有趣:
-fverbose-asm
在使用 -S
编译成汇编输出时非常有用,它会添加一些注释来增加信息量。
-finstrument-functions
在每个函数的进入和退出点处添加调用用户提供的分析函数的代码。
--coverage
对程序中的分支和调用进行插装,并创建一个覆盖率文件,在运行程序时产生覆盖数据,可以通过gcov
程序格式化,以帮助分析测试覆盖率。
-fsanitize={address
,
thread
,
undefined
}
分别启用 AddressSanitizer、ThreadSanitizer 和 UndefinedBehaviorSanitizer 代码检查器,这些程序会在运行时对程序进行各种类型的错误检查。
此前的答案还提到了-ftrapv
,但这个功能已经被-fsanitize=signed-integer-overflow
取代,后者是通过-fsanitize=undefined
启用的一种sanitizer之一。
-ftrapv
,请参考这里https://dev59.com/3XrZa4cB1Zd3GeqP6sUj ..看起来有一个长期等待修复的bug。 - Arjun Sreedharan始终使用 -O
或更高优化级别 (-O1
, -O2
, -Os
, 等等)。在默认的优化级别下,gcc 会选择编译速度而不做足够的分析来警告未初始化的变量等问题。
考虑采用 -Werror
策略,因为没有停止编译的警告往往会被忽视。
-Wall
基本上开启了很可能是错误的警告。
-Wextra
包含的警告倾向于标记常见的、合法的代码。它们可能对代码审查很有用(尽管类似 lint 程序发现了更多的陷阱并且更加灵活),但我不会在正常开发中打开它们。
如果项目开发人员对浮点数不熟悉,则使用 -Wfloat-equal
是一个好主意,否则就不是。
-Winit-self
是有用的;我想知道为什么它没有包括在 -Wuninitialized
中。
如果您有大量可移植的代码无法与 -pedantic
兼容,则使用 -Wpointer-arith
很有用。
此选项会将预处理和汇编的结果保存在文件中。
保存预处理后的源码对于调试宏非常有用。
保存汇编代码对于确定哪些优化生效非常有用。例如,您可能想要验证GCC是否对某些递归函数进行了尾调用优化,因为如果没有进行优化,您可能会造成堆栈溢出。
stepi
命令)。这对于编程非常有帮助。-fmudflap选项会在所有风险指针操作中添加运行时检查,以捕获未定义行为。这有效地使您的程序免疫缓冲区溢出,并有助于捕获各种悬空指针。
请参阅Mudflap指针调试
这是一个演示:
int main()
{
int a[10];
a[10] = 1; // <-- Oh noes, line 4
}
gcc -fmudflap mf.c -lmudflap
./a.out
输出:
*******
mudflap violation 1 (check/write): time=1280862302.170759 ptr=0x7fff96eb3d00 size=44
pc=0x7f3a575503c1 location=`mf.c:4:2 (main)'
/usr/lib/libmudflap.so.0(__mf_check+0x41) [0x7f3a575503c1]
./a.out(main+0x90) [0x400a54]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7f3a571e2c4d]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0xf9c560: name=`mf.c:3:6 (main) a'
bounds=[0x7fff96eb3d00,0x7fff96eb3d27] size=40 area=stack check=0r/3w liveness=3
alloc time=1280862302.170749 pc=0x7f3a57550cb1
number of nearby objects: 1
-fmudflap
选项,编译时会报出警告:warning: switch '-fmudflap' is no longer supported
。现已被AddressSanitizer取代。 - Agostino这并不是真正与C/C++相关,但无论如何它都很有用:
@file
将所有之前回答中提到的好标志(即您们已经指定的)放在一个“文件”中,并使用此上述标志一起使用该文件中的所有标志。
例如:
文件:compilerFlags
-Wall
-std=c99
-Wextra
然后进行编译:
gcc yourSourceFile @compilerFlags
-march=native用于为所编译的平台(芯片)生成优化代码。
这个选项不会帮助检测错误,但很少被提到的-masm=intel选项可大大改善使用-S
检查汇编输出的体验。
AT&T汇编语法让我头疼不已。
gcc -c [放置标志] -o myprog.o myprog.c
以编译(而非链接)C程序。 - Rory O'Kane