C的有用GCC标志

Mat*_*ner 154 c gcc compiler-flags

除了设置-Wall和设置之外-std=XXX,还有什么其他真正有用的,但是在C中使用的知名度较低的编译器标志?

我对任何其他警告特别感兴趣,和/或在某些情况下将警告转换为错误,以绝对最小化任何意外类型不匹配.

Alo*_*hal 135

这是我的:

  • -Wextra,-Wall:必不可少的.
  • -Wfloat-equal:有用,因为通常测试浮点数是否相等是不好的.
  • -Wundef:警告是否在#if指令中评估未初始化的标识符.
  • -Wshadow:当局部变量影响另一个局部变量,参数或全局变量时,或者每当内置函数被遮蔽时,都会发出警告.
  • -Wpointer-arith:警告,如果有什么取决于函数的大小或void.
  • -Wcast-align:每当指针被投射时警告,以便增加目标的所需对齐.例如,警告是否将a转换char *int *只能以两字节或四字节边界访问整数的on机器.
  • -Wstrict-prototypes:如果声明或定义了函数而未指定参数类型,则发出警告.
  • -Wstrict-overflow=5:警告编译器根据未发生签名溢出的假设进行优化的情况.(值5可能过于严格,请参见手册页.)
  • -Wwrite-strings:给字符串常量类型const char[长度,]以便将一个地址复制到非const char *指针将得到警告.
  • -Waggregate-return:警告是否定义或调用了返回结构或联合的任何函数.
  • -Wcast-qual:每当指针被强制转换为从目标类型*中删除类型限定符时发出警告.
  • -Wswitch-default:当switch声明没有default案例*时发出警告.
  • -Wswitch-enum:只要switch语句具有枚举类型的索引并且缺少case该枚举*的一个或多个命名代码,就会发出警告.
  • -Wconversion:警告可能改变值*的隐式转换.
  • -Wunreachable-code:警告编译器是否检测到代码永远不会被执行*.

那些标记*有时会发出太多的虚假警告,所以我会根据需要使用它们.

  • 相当完整的列表,只想再添加一个; `-Wformat = 2`:对printf/scanf函数的额外格式检查. (11认同)
  • 这些不都是“-Wall”所暗示的吗? (2认同)
  • @ chacham15,不,我不这么认为。http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html (2认同)
  • `-Wunreachable-code` 的功能已被删除(但是,如果仍在使用该选项,gcc 不会发出警告...) https://gcc.gnu.org/ml/gcc-help/2011-05/ msg00360.html (2认同)

caf*_*caf 64

一些-f代码生成选项很有趣:

  • -ftrapv函数将导致程序在有符号整数溢出时中止(在C中正式为"未定义的行为").

  • -fverbose-asm如果您正在编译-S以检查程序集输出,则它非常有用- 它会添加一些信息性注释.

  • -finstrument-functions 添加代码以在每个函数入口和出口点调用用户提供的分析函数.

  • -ftrapv 基本上被 -fsanitize=signed-integer-overflow 取代。 (2认同)

Gil*_*il' 52

始终使用-O或上述(-O1,-O2,-Os等等).在默认优化级别,gcc用于编译速度,并且没有做足够的分析来警告诸如单元化变量之类的事情.

考虑制定-Werror策略,因为不停止编译的警告往往会被忽略.

-Wall 几乎打开很可能是错误的警告.

包含在内的警告-Wextra倾向于标记共同的合法代码.它们可能对代码审查很有用(虽然lint风格的程序发现更多的陷阱更灵活),但我不会将它们用于正常开发.

-Wfloat-equal 如果项目的开发人员不熟悉浮点数,那么这是一个好主意,如果他们不熟悉则不是一个好主意.

-Winit-self很有用; 我想知道为什么它不包含在内-Wuninitialized.

-Wpointer-arith如果你有大多数可移植的代码无法使用,那么它非常有用-pedantic.

  • 如果项目中的开发人员不熟悉浮点数,那么"-Wfloat-equal"的+1是一个好主意,如果他们的话,那就不好了." 特别是它的下半部分.:-) (9认同)

cat*_*ive 38

-save-temps
Run Code Online (Sandbox Code Playgroud)

这留下了预处理器和组件的结果.

预处理源对调试宏很有用.

该程序集对于确定哪些优化生效非常有用.例如,您可能想要验证GCC是否在某些递归函数上进行尾调用优化,因为没有它,您可能会溢出堆栈.


小智 35

我很惊讶没有人说过这个 - 就我而言,最有用的标志是-g将调试信息放入可执行文件中,以便你可以调试它并逐步完成源代码(除非你精通并阅读汇编和stepi一个程序在执行时的命令).


Nor*_*ame 35

-fmudflap - 为所有危险的指针操作添加运行时检查以捕获UB.这有效地免疫你的程序缓冲区溢出,并有助于捕获各种悬空指针.

这是一个演示:

$ cat mf.c 
int main()
{
 int a[10];
 a[10]=1; // <-- o 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
Run Code Online (Sandbox Code Playgroud)

  • 自从GCC 4.9以来不再支持`-fmudflap`,你得到`警告:不再支持'-fmudflap'.它被AddressSanitizer取代了. (9认同)

Ami*_*mar 20

与C/C++没有多大关系,但无论如何都很有用:

@file
Run Code Online (Sandbox Code Playgroud)

将所有上述良好标志(您已指定)放在"文件"中,并使用上面的标志将该文件中的所有标志一起使用.

例如:

文件:compilerFlags

-壁

-std = C99

-Wextra

然后编译:

gcc yourSourceFile @compilerFlags
Run Code Online (Sandbox Code Playgroud)


Jen*_*edt 15

-march=native 为您正在编译的平台(=芯片)生成优化代码

  • 如果您正在为不了解目标的非本机计算机进行编译,则可以使用mtune = xxx,它在不使用指令集的情况下进行优化.例如,mtune = generic与"平均"案例处理器保持同步. (2认同)

siz*_*erz 14

如果您需要知道编译器预定义的预处理程序标志:

echo | gcc -E -dM -
Run Code Online (Sandbox Code Playgroud)


Mic*_*urr 13

它对于检测错误并没有多大帮助,但是很少提到的-masm=intel选项使得-S用于检查组件输出的更多,更好.

AT&T汇编语法对我的影响太大了.

  • AT&T和英特尔对我的区别在于C#和Java之间的区别.只是语法.两个都很糟糕.:) (2认同)
  • +1 @michael使gcc使用英特尔语法而不是上帝可怕的&t.检查组件使用足够的脑循环 - 不需要浪费src在操作码之前进行的脑循环.现在,如果只有gcc像其他编译器一样支持__asm {}内联,那么我们都已经完成了! (2认同)

Dav*_*ary 10

我的makefile通常包含

  CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
  ...
  g++ $(CFLAGS) -o junk $<
  gcc $(CFLAGS) -o $@ $<
  rm -f junk
Run Code Online (Sandbox Code Playgroud)

之前已经讨论过这些选项中最重要的选项,因此我将指出尚未指出的两个功能:

即使我正在开发一个代码库,它需要是普通的C,以便可移植到某些仍然没有像样的C++编译器的平台,我还是使用C++编译器(除了C编译器)进行"额外"编译.这有三个好处:

  1. C++编译器偶尔会给我提供比C​​编译器更好的警告消息.
  2. C++编译器接受-Weffc ++选项,它偶尔会给我一些有用的提示,如果我只在纯C中编译它,我会错过.
  3. 我可以保持代码相对容易移植到C++,避免一些边界条件,其中普通C代码是无效的C++代码(例如定义名为"bool"的变量).

是的,我是一个过于乐观盲目乐观,保持这种思维的任何一个月,现在一个平台,要么被宣布为过时,或者获得一个体面的C++编译器,我们终于可以切换到C++.在我看来,这是不可避免的 - 唯一的问题是,在管理层最终发布每个人都是小马之前或之后是否会发生这种情况.:-)

  • 我应该指出,C被弃用以支持C++永远不会发生,抱歉:) (6认同)
  • haha"struct namespace"在内核头文件中. (4认同)
  • 考虑-o/dev/null而不是rm -f junk (4认同)

nin*_*alj 9

-Wstrict-prototypes -Wmissing-prototypes
Run Code Online (Sandbox Code Playgroud)

  • 如果你必须处理那些认为K&R风格函数是个好主意的累犯,即使是原型声明,也可以使用`-Wold-style-definition`.(我必须和那样的人打交道.当我找到用K&R编写的新代码时,这真让我很烦恼.遗留的K&R东西已经很糟糕了,但新代码却很新!Grump !!!) (10认同)

Mat*_*ner 9

这是一个没有提到的伟大旗帜:

-Werror-implicit-function-declaration
Run Code Online (Sandbox Code Playgroud)

在声明之前每当使用函数时都会出错.


Joh*_*han 8

man gcc
Run Code Online (Sandbox Code Playgroud)

该手册充满了有趣的标志和良好的描述.但是,-Wall可能会使gcc尽可能冗长.如果您想要更多有趣的数据,您应该查看valgrind或其他一些工具来检查错误.

  • 感谢上帝,他们把它塞进了一个手册页,而不是那些那些神圣无法攻击的"信息"页面. (12认同)
  • 不过,这真是太棒了。`人海湾合作委员会| nl` 报告超过 11000 行。这不仅仅是臭名昭著的“bash”联机帮助页! (2认同)

Gre*_*ill 6

-Werror,它将所有警告视为错误并停止编译.该gcc手册页说明了你的编译器的每个命令行开关.


RWS*_*RWS 6

那么,也-Wextra应该是标准的.-Werror将警告变成错误(这可能非常烦人,特别是如果你没有编译-Wno-unused-result).如果您使用C99功能-pedantic,结合使用std=c89会给您额外的警告.

但那是关于它的.您无法将C编译器调整为比C本身更类型的保存.


cat*_*ive 6

-M* 选择范围.

这些让你编写make文件,自动找出你的c或c ++源文件应该依赖的头文件.GCC将使用此依赖关系信息生成make文件,然后将其从主要make文件中包含它们.

这是一个使用-MD和-MP的非常通用的makefile的例子,它将编译一个充满c ++源文件和头文件的目录,并自动找出所有依赖项:

CPPFLAGS += -MD -MP                                         
SRC = $(wildcard *.cpp)                                                       

my_executable: $(SRC:%.cpp=%.o)                                                        
        g++ $(LDFLAGS) -o $@ $^                                               

-include $(SRC:%.cpp=%.d)
Run Code Online (Sandbox Code Playgroud)

这是一篇博文,更深入地讨论了它:http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html


Mik*_*ike 5

我发现这个问题正在寻找一个标志来解决特定问题。我在这里没有看到它,所以我将添加一个在我的帖子中困扰我的内容:

-Wformat =2标志

-Wformat=> 检查对printfscanf等的调用,以确保提供的参数具有适合指定格式字符串的类型...

真正重要的部分(根据 GCC 手册):

-Wformat包含在-Wall. 为了更好地控制格式检查的某些方面,可以使用选项-Wformat-y2k-Wno-format-extra-args-Wno-format-zero-length-Wformat-nonliteral-Wformat-security和 ,-Wformat=2但不包含在 -Wall 中。

因此,仅仅因为您拥有-Wall并不意味着您拥有一切。;)