【问题标题】:MinGW doesn't produce warningsMinGW 不产生警告
【发布时间】:2015-02-06 10:49:22
【问题描述】:

我已在 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: format '%d' expects argument of type '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("%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。

【问题讨论】:

  • 什么版本? gcc --version
  • 我得到了相同的结果(也是 4.8.1)。有人应该告诉开发人员,因为这对我来说似乎是一个错误。
  • @mafso static __inline__ __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) int printf (const char *__format, ...) {...
  • 其实 mingw 相比 mingw64 有更多的 bug 和更少的 Windows 和新的 C 和 C++ 标准支持的功能,而且开发似乎也没有太大进展en.wikipedia.org/wiki/MinGW#MinGW-w64
  • @LưuVĩnhPhúc 谢谢你的建议。 MinGW-w64 没有这些问题。

标签: c windows gcc mingw


【解决方案1】:

使用std=c99 选项时缺少警告的问题看起来是因为MinGW 4.8.1 预处理stdio.h-std=c99 使用时与@ 相比对于printf() 系列函数略有不同使用 987654327@。

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

MinGW 在格式化浮点值方面存在一些兼容性问题,因为它在 C 运行时一直依赖 msvcrt.dll,并且 MSVC 使用 64 位表示 long double 而 gcc 使用 96 位 (或 x64 上的 128 位)表示。有关详细信息,请参阅gcc: printf and long double leads to wrong output. [C - Type conversion messes up]。更新的 MinGW 版本在 libmingwex.a 中提供了自己的 printf() 系列函数实现(名称带有 __mingw_ 前缀)来解决这些问题。

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

看来,如果要求符合 ANSI 标准,MinGW 将使用 libmingwex.a 实现(还有许多其他方法可以获取此配置 - 请查看标题以获取详细信息)。将用户对printf() 的调用连接到libmingwex.a 中的__mingw_printf() 实现是通过stdio.h 定义printf() 的静态内联实现来完成的,它是对__mingw_vfprintf() 调用的薄包装。显然,-Wformat 不适用于编译器认为不属于库的printf() 系列函数的版本(一个合理的假设——编译器对这些函数一无所知)。可以通过将适当的函数属性(例如:__attribute__ ((format (printf, 1, 2))))应用于静态内联包装函数来解决此问题。

您发现的另一个问题是printf("%lf\n", 3.14) 在使用std=c99 时打印0.000000,这看起来是__mingw_vfprintf()libmingwex.a 实现中的一个错误。似乎__mingw_vfprintf() 错误地将"%lf" 解释为参数是long double。我对此并不感到惊讶 - 我总是需要查看 %lf 是指 double 还是 long double

【讨论】:

  • 很好。我将引用 C 标准,因为我可以看到你已经习惯了。 "f,F A double argument representing a floating-point number ..."
  • 实际上不可能将float 传递给printf(),因为该类型的参数被提升为double。我想"%lf""%f" 是等价的,因此带有它们的格式字符串可以“回显”它们在scanf() 中的使用。但我不确定这些最近的 cmets 是关于什么的 - 答案表明 __mingw_vfprintf() 似乎错误地将 "%lf" 视为使用 long double 参数,因为它显然会为 "%lf" 和 @987654368 产生不同的输出@ 规格。并不是说"%lf" 应该与long double 类型一起使用。
  • %lf 中的 l 被明确忽略 - 单独的 %f 涵盖了 doublefloat 的使用(后者被向下转换)。它可以为那些认为需要它的人提供安慰,因为 l%ld 中用于长整数。
猜你喜欢
  • 2021-11-25
  • 2018-12-25
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多