我已经在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.h
和stdio.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
意味着double
或long double
。