我已经在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:警告:格式'%d'需要类型'int'的参数...
但命令gcc -std=c99 -Wall hello.c
没有发出任何警告。
两者都创建一个可执行文件 a.exe (运行并提供相同的结果)。
(有趣的是,命令gcc -std=gnu99 -Wall hello.c
会发出警告。)
我不知道这是不是一个bug,或者安装是否出错了,但是由于编译器工作并成功编译了一个更大的项目,所以两者似乎都不太可能(但是当使用-std = c99时,当然会忽略相同的警告)。
我一定错过了一些信息。
(ps:如果有人安装了新的MinGW,请测试一下。)
gcc版本4.8.1(GCC)
更新1:
在包含_GNU_SOURCE
之前定义stdio.h
即使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。
答案 0 :(得分:15)
使用std=c99
选项时缺少警告的问题看起来像是因为当{{1}时,MinGW 4.8.1预处理stdio.h
对于printf()
函数系列略有不同与使用-std=c99
时相比使用。
注意:我正在从TDM看MinGW 4.8.1 - 我认为其他发行版可能在这些细节上有所不同。
MinGW在格式化浮点值方面存在一些兼容性问题,因为它对C运行时的历史依赖-std=gnu99
以及MSVC对msvcrt.dll
使用64位表示的事实,而gcc使用了96位(或x64上的128位)表示。有关详细信息,请参阅gcc: printf and long double leads to wrong output. [C - Type conversion messes up]。更新版本的MinGW已经在long double
中提供了printf()
函数系列(名称上带有__mingw_
前缀)的自己实现,以解决这些问题。
标头文件libmingwex.a
和_mingw.h
配置是否将使用stdio.h
实施或libmingwex.a
实施。
似乎如果要求ANSI合规性,MinGW将使用msvcrt.dll
实现(还有许多其他方法来获取此配置 - 请查看标题以获取详细信息)。将用户调用libmingwex.a
与printf()
中的__mingw_printf()
实现联系,由libmingwex.a
定义stdio.h
的静态内联实现,这是一个很薄的包装器致电printf()
。显然__mingw_vfprintf()
没有应用于编译器认为不属于库的-Wformat
族函数版本(一个合理的假设 - 编译器对这些函数一无所知)功能)。通过将适当的函数属性(例如:printf()
)应用于静态内联包装函数,可以解决此问题。
您在使用__attribute__ ((format (printf, 1, 2)))
时printf("%lf\n", 3.14)
打印0.000000
时发现的另一个问题,似乎是std=c99
libmingwex.a
实施中的错误。似乎__mingw_vfprintf()
错误地解释__mingw_vfprintf()
意味着论证是"%lf"
。我对此并不感到惊讶 - 我总是要查找long double
是%lf
还是double
。