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

如何解决“格式中未知转换类型字符‘z’”编译器特定的警告?

孙梓
2023-03-14

我正在研究交叉编译到几个目标体系结构的代码。

我查看了在堆栈溢出中搜索“printf size\u t unknown conversion type character”警告的少量点击,但是这些帖子似乎都与minGW有关,因此这些答案,本质上是ifdef\u WIN32,不适用于我的基本相同问题实例,即,printf不识别“%zu”作为size\u t的格式说明符,但使用了mips交叉编译器。

是否有一个现有的编译器标志(用于指定的交叉编译器)使libc能够识别“%zu”作为size\t的格式说明符?

$ cat ./main.c
// main.c

#include <stdio.h>

int main( int argc, char* argv[] )
{
  size_t i = 42;
  printf( "%zu\n", i );
  return 0;
}

$ /path/to/mips_fp_le-gcc --version
2.95.3
$ 
$ file /path/to/libc.so.6
/path/to/libc.so.6: ELF 32-bit LSB pie executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.2.15, not stripped, too many notes (256)
$ 
$ /path/to/mips_fp_le-gcc -mips2 -O2 -EL -DEL -pipe -Wall -Wa,-non_shared -DCPU=SPARC -DLINUX -D_REENTRANT -DPROCESS_AUID -DTAGGING -fPIC -I. -I../../../root/include -I../include -I../../../common/include -I../../..
/root/include  -DDISABLE_CSL_BITE -DDISABLE_DNS_LOOKUP     -DOS=UNIX -DLINUX -DPOSIX_THREADS -D__USE_GNU -D_FORTIFY_SOURCE=2 -DHANDLE_CSL_DUPLICATES  -DOS=UNIX -DLINUX -DPOSIX_THREADS -D__USE_GNU -D_FORTIFY_SOURCE=2 -DHANDLE_CSL_DUPLICATES  -DOS=UNIX -DLINUX -DPOSIX_THREADS -D__USE_GNU -D_FORTIFY_SOURCE=2 -DHANDLE_C
SL_DUPLICATES  -DOS=UNIX -DLINUX -DPOSIX_THREADS -D__USE_GNU -D_FORTIFY_SOURCE=2 -DHANDLE_CSL_DUPLICATES -o ./main.o -c main.c 
main.c: In function `main':
main.c:6: warning: unknown conversion type character `z' in format
main.c:6: warning: too many arguments for format

如果对大胆问题的直接回答是“不”,那么还有什么其他可能的解决方案?想到的可能性是...

  1. register\u printf\u function()

...还有其他想法吗?我非常喜欢不涉及特定于目标的预处理器代码的解决方案,因此上述两个方案并不理想。

我认为(但不确定)交叉编译器版本是旧的;是否已知/保证有一个libc%zu识别为size_t的格式说明符?

更新:此交叉编译器似乎无法识别-std=c99;将其添加到编译器标志会生成错误“cc1:unknown C standard'c99”

共有2个答案

万俟渊
2023-03-14

您的gcc不支持z作为长度修饰符。这与MIPS无关,MIPS没有任何区别,而是2.95.3版本缺乏支持。

Z长度修饰符的支持是在1998年2月9日添加的,由Andreas Schwab提交"c-通用. c(format_char_info): Add new field zlen."。在此之前,有一个gcc扩展的Z作为size_t的转换类型说明符(而不是长度修饰符)。这段代码在gcc 2.95.3中,所以它应该能识别Z,但不能识别z

Joseph Myers于2000年7月17日添加了对z的支持,"c-通用. c(scan_char_table):允许diouxXn格式上的"z"长度修饰符"。尽管在时间上早于gcc 2.95.3,但这是在gcc 3分支中发布的,直到gcc 3.0才发布。所以你的古代编译器根本没有得到它。

因此,您可以将代码更改为使用Z,这仍然是受支持的。您还可以根据编译器版本定义宏:

#if __GNUC__ < 3
#define PZ "Z"
#else
#define PZ "z"
#endif  

然后在printf中使用它(“大小为%”PZ“u\n”,sizeof(int)) 您仍然需要修改代码。但最终不会有任何不同,因为在预处理器之后的格式字符串在较新的编译器上仍然是%zu,而在旧的编译器上仍然是%zu。将size\u t参数强制转换为其他参数的想法实际上会改变代码的结果,因为在某些情况下,它们会被强制转换为更大/更小的类型,具体取决于size\u t是什么以及您强制转换的对象

或者,如果您可以构建您的工具链,您可以修补gcc以了解z。我认为在"c-通用. c"中使用zlen的case语句中的一行更改就可以做到这一点。

register\u printf\u function()是glibc的一部分,glibc就是printf()代码所在的位置。它允许您在运行时使用新格式扩展printf。在编译时,您无法使用它来更改编译器。我不相信gcc在使用register\u printf\u function()进行printf类型检查时会知道添加了新的格式。

宦宏爽
2023-03-14

我使用的是一个很大的代码库,它是在几个不同的编译器下编译的,其中一些是旧的,并且不理解%z,所以我们只需要执行以下操作

printf("size = %d", (int)size);

当然,这是小尺寸的简单方法。如果尺寸可能很大,其他选择是

printf("size = %u", (unsigned)size);

printf("size = %lu", (unsigned long)size);

(还有其他明显的可能性)。

 类似资料:
  • 问题内容: 我有包含日期​​字符串的数据。 通常情况下,它会出现在“ Jan”中。1966年第3版的字型格式,但由于国际上的差异,不一定总是那样。 我需要读取数据并将其转换为标准日期字符串(’YYYY-MM-DD’)。 基本上这就是我到目前为止所拥有的: 问题答案: Xcode 9•Swift 4 或 Xcode 8.3.2•Swift 3.1 您可以按以下方式使用NSDataDetector:

  • 我有一个源类,它将字符串属性定义为CharSequence(不幸的是)。 所以如下: 给我: 无法将属性“java.lang.CharSequence charSeq”映射到“java.lang.String str”。考虑声明/实现一个映射方法:“java.lang.String map(java.lang.CharSequence value)” 我如何实现这个映射器方法,并使它对我的所有映射

  • 我正在堆栈中实现一个列表链接。该程序成功通过了所有必需的测试,但我遇到了此警告。程序的实现没有中断,但我正在寻求消除此问题。你能告诉我如何通过编辑Equals方法中的代码来修复它吗?未选中的强制转换:“java.lang.对象”到“LinkedStack”

  • 好的,我在Windows 7上使用MinGW(GCC 4.6.2)编译C文件时遇到了一个奇怪的问题。有问题的文件包含以下C代码: 编译结果是这样的: 现在,对我来说奇怪的是,它抱怨第6行的调用,而不是第4行的调用。我是错过了什么还是警告不正确?此外,是否有更好的格式字符串等效项?(我正在尝试将char变量打印为十六进制值。)

  • 问题内容: 我们总是被教导要确保在switch语句中使用 break 来避免掉线。 Java编译器会针对这些情况发出警告,以帮助我们避免犯小错误(而是严重错误)。 但是,我将案例检查作为功能使用(我们不必在这里进行介绍,但是它提供了一种非常优雅的解决方案)。 但是,编译器会吐出大量警告,这些警告可能会掩盖我需要了解的警告。我知道如何更改编译器以忽略所有掉线警告,但是我想在逐个方法的基础上实施此操作

  • 问题2:如何将这个日期值从转换为-作为pojo类中的静态方法?将其放入某个外部实用程序类中。 编辑#1:我对这些POJO使用模式。