用于uint32_t和size_t的 printf 格式说明符

printf format specifiers for uint32_t and size_t

提问人:ant2009 提问时间:7/3/2010 最后编辑:jwwant2009 更新时间:11/3/2021 访问量:317573

问:

我有以下几点

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

编译时收到以下警告:

format ‘%lu’ expects type ‘long unsigned int’, but argument has type ‘uint32_t’

当我使用夹板运行它时,我得到了以下内容:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

非常感谢您的任何建议,

c 打印f

评论

2赞 Jonathan Leffler 7/4/2010
C89 不支持 from 或 ;如果要使用这些类型,则应升级到 C89。作为扩展,GCC 可能确实允许您使用它们,但 C89 没有任何此类支持。uint32_t<stdint.h><inttypes.h>
14赞 Jonathan Leffler 7/4/2010
官方的 C99 格式修饰符是 'z',如 .size_t"%zu"
1赞 Ciro Santilli OurBigBook.com 10/25/2015
stackoverflow.com/questions/1401526/......
0赞 jww 10/19/2016
我相信@kenny的答案是最好的,但它缺乏.@u0b34a0f6ae的回答包括两者。uint32_tsize_t
1赞 bph 7/20/2017
乔纳森·莱夫勒(Jonathan Leffler)在第一条评论中第二次提到C89应该是C99

答:

40赞 Cogwheel 7/3/2010 #1

听起来你期望与(可能是 64 位)相同,而它实际上是(32 位)。在这两种情况下都尝试使用。size_tunsigned longunsigned int%zu

不过我不完全确定。

评论

1赞 ant2009 7/3/2010
编译时没有警告。但是,运行夹板我得到以下结果: 1) printf (%u) 期望无符号 int 得到 uint32_t: i 2) printf (%u) 期望无符号 int 得到 size_t: k
0赞 Cogwheel 7/3/2010
听起来夹板只是迂腐。它可能偏离了源代码中的类型名称,并且没有意识到它们是等效的。我想知道它会对@KennyTM的答案有什么影响......它当然应该更便携。
3赞 R.. GitHub STOP HELPING ICE 7/4/2010
夹板实际上是在做正确的事情。仅仅因为碰巧在您的编译器/平台上并不意味着它可能不在另一个编译器/平台上。与 .它实际上正在竭尽全力并做更多的工作来检测这个可移植性错误,因为简单、自然的检查就是像编译器一样尊重 typedef。int32_tintlongsize_t
5赞 u0b34a0f6ae 11/9/2011
-1,对不起,它不是便携式的。所需要的只是格式说明符和类型一致,并且您始终可以强制转换以使其为真。long 至少为 32 位,因此 with 始终正确。 更棘手,这就是在 C99 中添加的原因。如果你不能使用它,那么就把它当作(是 C89 中最大的类型,不太可能更大)。%lu(unsigned long)ksize_t%zuklongsize_t
162赞 kennytm 7/3/2010 #2

尝试

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

表示长度与 相同的整数,在 C99 标头 inttypes.h 中定义的宏表示无符号的 32 位整数。zsize_tPRIu32

评论

4赞 kennytm 7/3/2010
@robUK:呵呵。我建议你为夹板提交一个错误。
11赞 Dummy00001 7/3/2010
这是正确的答案。虽然我个人的建议是简单地投射,例如.否则,由于类型更改,以后会在整个代码中出现一堆警告。printf( "%lu", (unsigned long )i )
1赞 R.. GitHub STOP HELPING ICE 7/3/2010
这是正确的答案。我同意 KennyTM 关于为夹板提交错误的观点。顺便说一句,“%zu”是size_t的正确格式。您不需要任何 PRI* 宏来打印size_t。
1赞 alcor 10/15/2013
如果我没记错的话,%zu 是 C99,在问题中他写了“C89”。
9赞 Colin D Bennett 10/25/2013
@alcor是的,他确实放置了 C89(显然是他正在使用的 gcc 编译器标志),但他正在使用,所以实际上它是 C99 代码,应该这样编译。uint32_t
20赞 R.. GitHub STOP HELPING ICE 7/3/2010 #3

如果您不想使用 PRI* 宏,打印任何整数类型的另一种方法是分别转换为 或 和 使用 或。这对于未定义 PRI* 宏的 POSIX(或其他操作系统)类型特别有用,例如。intmax_tuintmax_t"%jd"%juoff_t

33赞 u0b34a0f6ae 11/9/2011 #4

所需要的只是格式说明符和类型一致,并且您始终可以强制转换以使其为真。 至少为 32 位,因此与一起始终正确:long%lu(unsigned long)k

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_t更棘手,这就是在 C99 中添加的原因。如果你不能使用它,那么就把它当作(是 C89 中最大的类型,不太可能更大)。%zuklongsize_t

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

如果不能为所传递的类型正确设置格式说明符,则相当于从数组中读取过多或过少的内存。只要使用显式强制转换来匹配类型,它就是可移植的。printf