为什么 Mingw-w64 gcc 编译器会生成关于 %zd 和 %a 格式的错误警告

why will Mingw-w64 gcc compiler generate wrong warning about the format of %zd and %a

我正在使用 gcc 编译器,命令行是

{gcc 'hellowo.c' -o 'hellowo.exe' -Wall -g -O2 -static-libgcc -std=c11 -fexec-charset=GBK}

版本信息是

gcc version 8.1.0 (x86_64-win32-seh-rev0, Built by MinGW-W64 project)

当我尝试时

#include <stdio.h>

int main(void)
{
    float float1 = 64.25f;
    printf("%zd\n",sizeof(int));
    printf("%a",float1); //float1=64.25f
    return 0;
}

编译器警告我:

hellowo.c: In function 'main':
hellowo.c:6:12: warning: unknown conversion type character 'z' in format [-Wformat=]
     printf("%zd\n",sizeof(int));
            ^~~~~~~
hellowo.c:6:12: warning: too many arguments for format [-Wformat-extra-args]
hellowo.c:6:12: warning: unknown conversion type character 'z' in format [-Wformat=]
hellowo.c:6:12: warning: too many arguments for format [-Wformat-extra-args]
hellowo.c:7:12: warning: unknown conversion type character 'a' in format [-Wformat=]
     printf("%a",float1); //float1=64.25f
            ^~~~
hellowo.c:7:12: warning: too many arguments for format [-Wformat-extra-args]
hellowo.c:7:12: warning: unknown conversion type character 'a' in format [-Wformat=]
hellowo.c:7:12: warning: too many arguments for format [-Wformat-extra-args]

然而输出是

4
0x1.010000p+6

为什么会这样,我是用C primer plus的例子自己研究

真奇怪,.exe可以正常运行,我的程序也可以编译成功。

我尝试将 %zd 修改为 %zu,(“%zd”语句是 C 入门加 的示例)

仍然有警告:

hellowo.c:6:12: warning: unknown conversion type character 'z' 
in format [-Wformat=]
     printf("%zu\n",sizeof(int));
            ^~~~~~~
hellowo.c:6:12: warning: too many arguments for format [-Wformat-extra-args]
hellowo.c:6:12: warning: unknown conversion type character 'z' 
in format [-Wformat=]
hellowo.c:6:12: warning: too many arguments for format [-Wformat-extra-args]

为什么 Mingw-w64 gcc 编译器会产生关于 %zd 和 %a 格式的错误警告?

这是一个不完整的答案。

您的编译器未实现 printf 函数及其支持的格式。它们由运行时库实现。对于 MinGW,编译器是 gcc 的一个版本,如果我没记错的话,运行时库是 Microsoft 为 Windows.

提供的那个

gcc 编译器还可以对它认为不正确的 printf 格式字符串发出警告,例如,如果您尝试使用 %s 来打印 int 类型的参数。它必须对运行时库支持的内容做出一些假设。通常它只是遵循 C 标准的规则。但是对于 -std=c11,我很惊讶它会抱怨 %zd%a,它们自 C99 以来一直是有效的 C。 (某些版本的 Microsoft 运行时库可能不支持它们,但这应该不会影响编译时行为。)

最重要的是,由于某些未知原因,您的编译器已决定它无法识别这些格式,但运行时库中 printf 的实现可以正确处理它们。您的编译器和运行时库之间某处不匹配。 gcc 可能使用一些试探法来猜测不支持 C99 中引入的某些格式,并且在这种情况下猜测错误。也许微软最近更新了它的运行时库,而 gcc 还没有跟上变化。

这些警告不应影响您的程序在编译和链接后的行为。

顺便说一句,size_t 值的正确格式是 %zu,而不是 %zd,因为 size_t 是无符号类型。 %zd 可能在这种情况下有效,但无论如何都使用 %zu

我能够在 Cygwin 下使用 x86_64-w64-mingw32-gcc.exe(版本 7.4.0)重现该问题。删除 -Wall 禁止警告。

您可以通过将选项 -D__USE_MINGW_ANSI_STDIO 传递给 gcc 来避免该问题。这导致它对 printf.

使用不同的实现