uint32_t 和 size_t 的 printf 格式说明符
Posted
技术标签:
【中文标题】uint32_t 和 size_t 的 printf 格式说明符【英文标题】:printf format specifiers for uint32_t and size_t 【发布时间】:2022-01-23 02:40:39 【问题描述】:我有以下
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
非常感谢您的建议,
【问题讨论】:
C89 不支持来自<stdint.h>
或<inttypes.h>
的uint32_t
;如果你想使用这些类型,你应该升级到 C89。作为扩展,GCC 可能确实允许您使用它们,但 C89 没有任何此类支持。
size_t
的官方 C99 格式修饰符是“z”,如 "%zu"
。
***.com/questions/1401526/…
我相信@kenny 的答案最适合uint32_t
,但它缺少size_t
。 @u0b34a0f6ae 的答案包括两者。
Jonathan Leffler 在第一条评论中第二次提到 C89 应该是 C99
【参考方案1】:
听起来您希望size_t
与unsigned long
(可能是64 位)相同,而实际上它是unsigned int
(32 位)。在这两种情况下都尝试使用%zu
。
但我并不完全确定。
【讨论】:
编译时没有警告。但是,运行夹板我得到以下信息:1)printf(%u)期望 unsigned int 得到 uint32_t:i 2)printf(%u)期望 unsigned int 得到 size_t:k 听起来夹板只是迂腐。它可能与源代码中的类型名称不同,并且没有意识到它们是等价的。我想知道@KennyTM 的回答会做什么......它当然应该更便携。 夹板实际上是在做正确的事情。仅仅因为int32_t
在您的编译器/平台上恰好是 int
并不意味着它可能不在另一个 long
上。 size_t
也一样。它实际上正在竭尽全力并做更多工作来检测这个可移植性错误,因为简单、自然的检查就是像编译器一样尊重 typedef。
-1,抱歉它不便携。所需要的只是格式说明符和类型一致,并且您始终可以强制转换以实现这一点。 long 至少是 32 位,所以 %lu
和 (unsigned long)k
总是正确的。 size_t
比较棘手,这就是为什么在 C99 中添加了 %zu
。如果你不能使用它,那么就像k
一样对待它(long
是C89中最大的类型,size_t
不太可能更大)。【参考方案2】:
试试
#include <inttypes.h>
...
printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);
z
表示长度与size_t
相同的整数,PRIu32
宏 defined in the C99 header inttypes.h
表示无符号 32 位整数。
【讨论】:
@robUK:呵呵。我建议你提交一个关于夹板的错误。 这是正确的答案。虽然我个人的建议是简单地投射,例如printf( "%lu", (unsigned long )i )
。否则,由于类型更改,稍后会在整个代码中出现一堆警告。
这是正确答案。我同意 KennyTM 关于提交夹板错误的意见。顺便说一句,“%zu”是 size_t 的正确格式。您不需要任何 PRI* 宏来打印 size_t。
如果我没记错的话 %zu 是 C99,在问题中他写了 'C89'。
@alcor 是的,他确实放了 C89(显然是他正在使用的 gcc 编译器标志),但他使用的是 uint32_t
所以实际上它是 C99 代码,应该这样编译。【参考方案3】:
如果您不想使用 PRI* 宏,另一种打印 ANY 整数类型的方法是强制转换为 intmax_t
或 uintmax_t
并使用 "%jd"
或 %ju
, 分别。这对于没有定义 PRI* 宏的 POSIX(或其他操作系统)类型特别有用,例如 off_t
。
【讨论】:
【参考方案4】:所需要的只是格式说明符和类型一致,并且您始终可以强制转换以实现这一点。 long
至少是 32 位,所以 %lu
和 (unsigned long)k
总是正确的:
uint32_t k;
printf("%lu\n", (unsigned long)k);
size_t
比较棘手,这就是为什么在 C99 中添加了%zu
。如果你不能使用它,那就像k
一样对待它(long
是C89中最大的类型,size_t
不太可能更大)。
size_t sz;
printf("%zu\n", sz); /* C99 version */
printf("%lu\n", (unsigned long)sz); /* common C89 version */
如果你没有得到正确的格式说明符,那么printf
将相当于从数组中读取太多或太少的内存。只要您使用显式类型转换来匹配类型,它就可以移植。
【讨论】:
【参考方案5】:How do I print uint32_t and uint16_t variables' value?
#include <stdio.h> // need at least one of these two
#include <inttypes.h>
int main (void)
uint32_t a=1234;
uint16_t b=5678;
printf("%" PRIu32 "\n",a);
printf("%" PRIu16 "\n",b);
return 0;
【讨论】:
链接的问题谈到uint32_t
,但是size_t
呢?以上是关于uint32_t 和 size_t 的 printf 格式说明符的主要内容,如果未能解决你的问题,请参考以下文章
什么是 uint_fast32_t,为什么要使用它来代替常规的 int 和 uint32_t?
C语言之如何输出uint32_t和uint64_t和16进制