Sto*_*row 6 c printf mips cross-compiling format-specifiers
我正在处理交叉编译到多个目标架构的代码。
我看着少数 的 点击来自搜索堆栈溢出的的“printf的size_t未知的转换型性格”的警告,但这些职位似乎都涉及到minGW,所以这些问题的答案,基本上是ifdef荷兰国际集团对抗_WIN32,并不适用于我的基本上是相同的实例问题,即printf不识别“ %zu”作为 的格式说明符size_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
Run Code Online (Sandbox Code Playgroud)
如果对粗体问题的直接回答是“否”,那么其他可能的解决方案是什么?想到的可能性是……
register_printf_function()minGW特定帖子) ……还有其他想法吗?我非常喜欢不涉及特定于目标的预处理器代码的解决方案,因此上述两个并不理想。
我认为(但不确定)交叉编译器版本是旧的;是否已知/保证上述工具链的较新版本具有libc识别“ %zu”作为格式说明符的功能size_t?
更新:这个交叉编译器似乎无法识别-std=c99;将它添加到编译器标志会产生错误“ cc1: unknown C standard 'c99'”
您的 gcc 不支持z长度修饰符。这与MIPS无关,完全没有区别,而是2.95.3版本缺乏支持。
Z1998 年 2 月 9 日添加了对长度修饰符的支持,由 Andreas Schwab 提交“c-common.c (format_char_info):添加新字段 zlen。”。在此之前有一个 gcc 扩展Z作为转换类型说明符(而不是长度修饰符)size_t。该代码位于 gcc 2.95.3 中,因此它应该识别Z,但不能识别z。
zJoseph Myers 于 2000 年 7 月 17 日添加了对“c-common.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
Run Code Online (Sandbox Code Playgroud)
然后使用它,如printf("The size is %"PZ"u\n", sizeof(int)); 您仍然需要修改您的代码。但最终不会有任何不同,因为格式字符串在预处理器之后仍然存在于%zu较新的编译器和%Zu旧的编译器上。size_t将参数强制转换为其他类型的想法实际上会改变代码的结果,因为在某些情况下它们将被强制转换为更大/更小的类型,具体取决于size_t是什么以及您强制转换的类型。
或者,如果您可以构建工具链,则可以修补 gcc 以了解z. 我认为对“c-common.c”中使用的 case 语句进行一行更改zlen就可以了。
register_printf_function()是 glibc 的一部分,这是printf()代码所在的地方。它将允许您在运行时使用新格式扩展 printf。在编译时你无法用它做任何改变编译器的事情。register_printf_function()而且我不相信 gcc 在使用时进行 printf 类型检查时能够知道添加了新格式。