为什么 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
.
使用不同的实现
我正在使用 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
.