当前位置: 首页 > 知识库问答 >
问题:

MinGW GCC:"未知的转换类型字符' h'" (snprintf)

彭博厚
2023-03-14

好的,我在Windows 7上使用MinGW(GCC 4.6.2)编译C文件时遇到了一个奇怪的问题。有问题的文件包含以下C代码:

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("%2hhX\n", 250);
    char c[80];
    snprintf(c, sizeof(c), "%2hhX", 250);
    printf("%s\n", c);
    return 0;
}

编译结果是这样的:

$ gcc.exe -std=c99 -pedantic -Wall test.c
test.c: In function 'main':
test.c:6:2: warning: unknown conversion type character 'h' in format [-Wformat]
test.c:6:2: warning: too many arguments for format [-Wformat-extra-args]

现在,对我来说奇怪的是,它抱怨第6行的snprintf调用,而不是第4行的printf调用。我是错过了什么还是警告不正确?此外,是否有更好的格式字符串"%2hhX"等效项?(我正在尝试将char变量打印为十六进制值。)

共有2个答案

华凯捷
2023-03-14

除了另一个答案,这里还有一些关于GCC中printf格式检查的更多信息:

当您说__attribute__((__format__(格式,...))))时格式的值可以是(就 printf 而言)以下之一:printfgnu_printf ms_printf

ms_printf使 GCC 假定该函数采用用于微软视觉工作室 CRT 打印f 系列函数的格式字符串。这意味着海湾合作委员会将抱怨zhhll,但会在没有警告的情况下通过I64

gnu_printf使GCC假定下面是gnu libc printf实现(或者可能只是符合POSIX/C99的printf实施,我不确定)。因此,GCC将投诉I64和其他Microsoft扩展,但将接受z

printf在为Windows编译时是ms_printf的别名,否则是gnu_printf的别名。

请注意,此检查与正在使用的实际printf实现完全正交。如果您编写自己的类似printf的函数并将__attribute__((__format__(FORMAT,…)))放在上面,这很容易看到——GCC会根据FORMAT抱怨不同的事情,但是您可以在函数内部做任何您想做的事情。

我知道的可用的printf实现:

  • MinGW中的MinGW ANSI STDIO(编译时使用-D_USE_MinGW_ANSI_STDIO=1)。org和MinGW-w64工具链。符合ms_printf(完全?)和gnu_printf格式(部分-不支持位置参数)
  • MSVCRT(编译时不带-D_USE_MINGW_ANSI_STDIO=1)。符合ms_printf(duh…),符合 的程度很低,并且取决于运行时版本(旧版本不支持 ll,新版本支持;到目前为止,任何版本都不支持zhh
  • 格努里布。完全(或接近完全)符合ms_printfgnu_printf

MinGW.org的< code>stdio.h头不使用< code >属性格式

标准。MinGW-w64中的hheader对MinGW ANSI STDIO实现使用属性格式gnu_printf,但对MSVCRT实现不使用任何内容。修复:在更新版本的MinGW-w64头stdio中。h将使用属性格式ms_printfMSVCRT实现。

gnulib完全了解< code>printf和< code>gnu_printf之间的区别,并且会根据一些复杂的宏来选择其中的一个(可能会附带一个适当的实现来支持该格式所说的功能)。

已知(目前)在GCC格式检查方面有问题的软件:

  • glib-使用printf格式,但实现来自gnulib;将其更改为gnu_printf
  • 有一个突出的错误
  • CPython-代码充满了z格式,但官方二进制文件是针对MSVCRT构建的;它还在其扩展标头中使用printf格式,即使扩展也经常使用z
白智
2023-03-14

从历史上看,MinGW一直处于一种奇怪的情况,尤其是就C99支持而言。MinGW主要依赖于随Windows分发的msvcrt.dll运行时,而该运行时不支持C99。

因此,对于较旧版本的MinGW,在使用C99特定的格式说明符时,您可能会在C99模式下遇到问题。同样从历史上看,GCC没有对msvcrt做出任何特殊调整.dll缺乏对C99指定符的支持。因此,您会遇到 -Wformat 不会警告不起作用的格式的情况。

双方的情况都在改善-当与MS运行时一起使用时,GCC对-Wformat有特定的支持,例如:

  • -Wpedia antic-ms-format这样GCC就不会抱怨"I32""I64"(即使它被记录在案,我仍然收到投诉,即使在4.7.0中也无法识别它-也许它是全新的)
  • ms_printf选项__attribute__((__format__))

另一方面,MinGW提供自己的< code>snprintf()已经有一段时间了,因为MSVC的变体< code>_snprintf()表现得非常不同。然而,在msvcrt.dll,MinGW长期依赖于< code>printf(),所以< code>printf()的C99格式说明符不起作用。在某个时候,MinGW开始提供它自己版本的< code>printf()和朋友,这样你就可以得到正确的C99(和GNU?)支持。然而,似乎是保守的一面,这些并没有取代msvcrt.dll的版本。它们的名称类似于< code>__mingw_printf()。

看起来在4.6.1和4.7.0之间的某个时间点,MinGW标头开始使用MinGW提供的版本作为msvcrt.dll函数的替代品(至少如果您指定了C99)。

然而,在新版本中,GCC和MinGW似乎仍然有点不同步。和以前一样,GCC不会警告那些在MinGW上实际上不起作用的说明符,也不会抱怨那些会起作用的说明符。

您可能想尝试以下代码片段,看看您的MinGW版本对"hhX"的支持程度:

printf("%hhX\n", 0x11223344);
__mingw_printf("%hhX\n", 0x11223344);

我不知道该建议什么来解决您遇到的问题-我认为您可能能够修补MinGWstdio。h头,以便它在printf函数上有一个__attribute__((__format__(gnu_printf,…))attribute属性(它们不在较新的stdio.h中,所以GCC将使用它的默认格式支持)。

 类似资料:
  • 2.3.4 字符串类型与其他类型的转换 应用程序中有时需要将字符串类型的数据转换成其他数据类型,或者相反。下面介绍Python 中如何实现这些功能。 首先看函数 eval()。eval 函数接收一个字符串,并将该字符串解释成 Python 表达式 进行求值,最终得到特定类型的结果值;如果字符串无法解释成合法的 Python 表达式则报 错(如语法错误、未定义变量错误等)。例如: >>> eval(

  • 问题内容: 我正在从在Varchar中具有原始提要的表中导入数据,我需要将varchar中的列导入到字符串列中。我尝试使用以及,但是却遇到了错误,因为有一些空字段,我需要将它们作为空或null检索到新表中。 请让我知道是否有相同的功能。 问题答案: 大胆猜测:如果您的值是一个空字符串,则可以使用NULLIF将其替换为NULL:

  • 问题内容: 在上次考试中,我们进行了练习以确定以下代码的输出: 我的回答是,但现在我意识到这是错误的答案。应该是。但为什么? 问题答案: 假设您的语法是: 表达式是从左到右求值的,在这种情况下,2 + 3求和为5,当“添加”到字符串结果为时,将其加到1时,再加上1,结果是:

  • 问题内容: 最近,我试图用Python存储和读取文件中的信息,但遇到一个小问题:我想从文本文件中读取类型信息。从字符串到int或float的类型转换非常有效,但是从字符串到类型的类型转换似乎是另一个问题。自然,我尝试过这样的事情: 但是,它并不用作强制类型转换,而是用作查找变量类型的机制,实际上它在这里。 我找到了一种解决方法: 但我一般尽量避免类似的功能/报表或在那里我可以。所以我的问题是:是否

  • 本文向大家介绍jquery把int类型转换成字符串类型的方法,包括了jquery把int类型转换成字符串类型的方法的使用技巧和注意事项,需要的朋友参考一下 jQuery中把获取的number类型数据转换成字符串类型 以上就是小编为大家带来的jquery把int类型转换成字符串类型的方法全部内容了,希望大家多多支持呐喊教程~

  • 我取一些产品从服务器,但我得到了一个错误,说明另一个例外被抛出:不正确使用家长DataWidget。同步快照 这是我的ProductModel课程 这是主页 这是JsonResorts