如何让 MinGW GCC 识别 size_t 的 %zu 格式说明符?

How to get MinGW GCC to recognize the %zu format specifier for size_t?

一图胜千言:

我知道如何解决这个问题。但我如何在 Microsoft 中修复它,这样我什至都不会收到警告?

编辑:

  1. 与其他人在评论中指出的相反,这是特定于 Microsoft 系统的。我可以 运行 在 linux 机器上使用完全相同的代码,在相同版本的 VsCode 中使用相同的配置(tasks.json 和 properties.json),使用相同版本的 gcc,我不会收到这些编译器警告。
  2. 我使用的 C 标准是 c17。
  3. 尝试在依赖于格式的函数(如 printf 和 scanf)中使用格式说明符如“%z”(甚至“%ll”)将触发格式编译器警告,即使在完全更新(自 08/ 2021) Windows 10 OS,使用最新的 mingw-64 工具链(具体来说,gcc 8.1.0——这里使用的编译器)。
  4. 图中显示的“编译器错误”实际上只是一个被视为错误的格式警告(引用编译器:“[-Werror=format=]”)
  5. 谢谢,“@the busybee”。你试图解决这个问题。这确实是一个很好的解决方法,但它会影响开发兼容性。

编辑 2:

在 运行解决 导致实际意外错误 的格式不兼容问题之后(以及在 Windows 上使用 GDB 高级功能的可怕经历之后),我刚刚决定在 Windows 上永远放弃 GNU。对于 Windows 机器上的 C 跨平台开发,我现在使用 Clang。到目前为止,我对这个决定 100% 满意。谢谢大家花时间帮助我。

MinGW 默认使用微软的运行time 库,所以printf() 的格式字符串被选中,因为MinGW 项目认为微软支持它。显然 %zu 被视为不受支持,这可能不一定是正确的。 (在 Windows 10 上使用 MinGW64 的 GCC 8.1.0 快速检查显示警告,但有效。)

但是,MinGW 还附带了一组替代实现。要使用它们,请在函数名称前加上 __mingw_(例如 __mingw_printf)。

根据项目的性质,您可能希望全局 #define printf __mingw_printf 或使用 -D__USE_MINGW_ANSI_STDIO(它启用所有 printf 系列函数的 MinGW 版本)。

另一个避免警告的方法是对编译器隐藏格式字符串,例如将它放在另一个模块中,或者在 运行-time 期间构造它。

值得指出这里的根本问题是什么,即:严重违反 "don't repeat yourself" 原则。我们有一个库函数,printf,它在 运行 时间将解析它的格式字符串并尝试打印一些东西。然后我们在 C 编译器中有一段完全不同的代码,它将在编译时解析相同的格式字符串,并警告用户潜在的问题。

使用 Windows 下的 MinGW,问题变得更加复杂,因为这两个解析器是由两组完全不同的人编写和维护的,他们之间没有任何联系。 (至少在 Linux 下,从事 gcc 工作的人和从事 glibc 工作的人之间有很多协调。)

因此,对于接受的内容,两个解析器之间没有完全一致也就不足为奇了。 (事实上​​,如果达成完美一致,那将是一个奇迹。)this question 的答案在一定程度上描述了 2012 年的协调有多么不完美,而我们在 10 年后仍然不完美。

不完美是游戏的名称,可能没有完美的解决方案。我不得不相信,在 2021 年,微软的 C 运行-time library 确实 支持 %zu。但是,如果 MinGW 中内置的最新版本的 gcc 没有赶上这个事实,如果它仍然警告 z 修饰符不受支持,那么您可能无能为力。您可以向 MinGW 人员发送错误报告,他们最终可能会对此采取行动,但与此同时,您今天已经有了需要编译的代码。您可以关闭 -Wformat,但您可能不想(我确实不想),因为您可能希望 -Wformat 继续检查您可能犯的其他错误。

我所在的团队维护着一个庞大、成熟、跨平台的代码库,虽然这是一个我非常想使用的理想解决方案,但我们仍然不经常使用 %zu,因为我们仍然不能确定我们使用的每个编译器和每个 运行-time 库都同意它。

我这么说并不是建议您也放弃 %zu,而只是为了表达我的同情:即使在 2021 年,安全和便携地打印 size_t 值仍然非常困难.