-3

一张图片胜过一千个字:

微软几十年来一直在失败的 C 开发人员

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

编辑:

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

编辑2:

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

4

2 回答 2

1

值得指出的是这里的根本问题,即:一个巨大的、公然违反“不要重复自己”原则的行为。我们有一个库函数 ,printf它在运行时会解析它的格式字符串并尝试打印一些东西。然后我们在 C 编译器中有一段完全不同的代码,它将在编译时解析相同的格式字符串,并警告用户潜在的问题。

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

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

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

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

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

于 2021-08-24T12:37:20.213 回答
0

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

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

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

避免警告的另一个选项是对编译器隐藏格式字符串,例如将其放入另一个模块中,或在运行时构造它。

于 2021-08-24T06:22:23.010 回答