MinGW不会产生警告
我已经在Windows 7 32位机器上成功安装了MinGW,并试图使用命令行或MinGW控制台编译一个简单的程序。
该代码在printf语句中存在故意错误:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
printf("%dn" , 3.14 ) ;
return 0 ;
}
命令gcc -Wall hello.c
给出了正确的警告:hello.c:7:2:warning:格式'%d'需要'int'类型的参数...
但是命令gcc -std=c99 -Wall hello.c
不会给出任何警告。
两者都创建一个可执行的a.exe(运行并提供相同的结果)。
(有趣的是,一个命令gcc -std=gnu99 -Wall hello.c
给出警告。)
我不知道这是一个错误,还是安装程序出错,但是这两者似乎都不太可能,因为编译器工作并成功编译了一个更大的项目(但是当使用-std = c99时忽略了相同的警告)。
我必须错过一些信息。
(ps:如果有人安装了新的MinGW,请对此进行测试。)
gcc版本4.8.1(GCC)
更新1:
在包含stdio.h
之前定义_GNU_SOURCE
即使使用gcc -Wall hello.c
也会删除警告。
更新2(可能不太相关):
编译
printf("%lfn" , 3.14 ) ;
-std=c99
标志输出:0.000000
-std=gnu99
输出:3.140000
并编译:
printf("%fn" , 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.h
和stdio.h
配置是否使用libmingwex.a
实现或msvcrt.dll
实现。
看起来,如果要求ANSI合规性,MinGW将使用libmingwex.a
实现(还有许多其他方法也可以获得此配置 - 查看标题以了解详细信息)。 接线,用户调用printf()
的__mingw_printf()
实施libmingwex.a
被做stdio.h
定义的静态连续实施printf()
是围绕一个电话薄包装到__mingw_vfprintf()
显然, -Wformat
不适用于编译器不认为是库的一部分的printf()
系列函数的版本(一个合理的假设 - 编译器并不真正了解这些函数的任何内容)。 通过将适当的函数属性(例如: __attribute__ ((format (printf, 1, 2)))
)应用于静态内联包装函数,可以解决此问题。
您发现的另一个问题是,在使用std=c99
时, printf("%lfn", 3.14)
std=c99
0.000000
,看起来是libmingwex.a
实现__mingw_vfprintf()
中的一个错误。 似乎__mingw_vfprintf()
错误地将"%lf"
解释为意味着该参数是一个long double
__mingw_vfprintf()
。 我对此并不感到惊讶 - 我总是必须查看%lf
是指double
还是long double
。