MinGW不会产生警告

我已经在Windows 7 32位机器上成功安装了MinGW,并试图使用命令行或MinGW控制台编译一个简单的程序。

代码在printf语句中有故意的错误:

#include <stdio.h> #include <stdlib.h> int main( void ) { printf("%d\n" , 3.14 ) ; return 0 ; } 

命令gcc -Wall hello.c给出了一个正确的警告: hello.c:7:2:warning:格式'%d'需要'int'types的参数。

但是命令gcc -std=c99 -Wall hello.c不会给出任何警告。

两者都创build一个可执行的a.exe (运行并给出相同的结果)。

(有趣的是一个命令gcc -std=gnu99 -Wall hello.c给出警告。)

我不知道这是一个错误还是安装程序出错,但是由于编译器工作并成功编译了一个更大的项目(但是当使用-std = c99时忽略了相同的警告),这两者似乎都不太可能。

我必须错过一些信息。

(ps:如果有人有新的MinGW安装,请testing这个。)

gcc版本4.8.1(GCC)

更新1:

在包含stdio.h之前定义_GNU_SOURCE即使使用gcc -Wall hello.c也会删除警告。

更新2(可能不太相关):

编译

  printf("%lf\n" , 3.14 ) ; 

-std=c99标志输出:0.000000

-std=gnu99输出:3.140000

并编译:

  printf("%f\n" , 3.14 ) ; 

-std=gnu99-std=c99输出:3.140000

更新3:

似乎受到影响的函数是:printf,fprintf,snprintf,sprintf。

使用std=c99选项时缺少警告的问题看起来像是因为当使用-std=c99时,MinGW 4.8.1预处理stdio.h对于printf()系列函数稍有不同,与-std=gnu99

注意:我正在从TDM看MinGW 4.8.1 – 我认为其他发行版可能在这些细节上有所不同。

MinGW与格式化浮点值有一些兼容性问题,因为它历史上依赖msvcrt.dll的C运行时和事实,MSVC使用64位表示long double而gcc使用96位(或128位在x64)表示。 请参阅gcc:printf和long double导致错误的输出。 [C – 类型转换混淆了]一些细节。 MinGW的更新版本已经在libmingwex.a提供了自己的printf()系列函数的实现(在名称上带有__mingw_前缀)来解决这些问题。

头文件_mingw.hstdio.h配置是否使用libmingwex.a实现或msvcrt.dll实现。

看起来,如果要求ANSI合规,MinGW将使用libmingwex.a实现(还有许多其他的方式来获得这个配置 – 查看标题的细节)。 将用户调用printf()连接到__mingw_printf()中的__mingw_printf()实现由stdio.h完成,该printf()定义了printf()一个静态内联实现,该实现是对__mingw_vfprintf()的调用。 显然, -Wformat并不适用于编译器不认为是库的一部分的printf()系列函数的版本(一个合理的假设 – 编译器并不真正了解这些函数的任何内容)。 通过将相应的函数属性(例如: __attribute__ ((format (printf, 1, 2))) )应用于静态内联包装函数,可以解决此问题。

另一个问题是,在使用std=c99时, printf("%lf\n", 3.14) std=c99 0.000000 ,看起来是libmingwex.a实现__mingw_vfprintf()中的一个错误。 似乎__mingw_vfprintf()错误地将"%lf"解释为意味着参数是一个long double __mingw_vfprintf() 我对此并不感到惊讶 – 我总是要查找是否%lf意味着doublelong double