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_tunsigned 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_tuintmax_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?

使用 SIMD 搜索密钥

uint32_t 和 u_int32_t 的区别

C语言之如何输出uint32_t和uint64_t和16进制

从uint32_t [16]数组到uint32_t变量序列的64位副本

如何将 32 字符(0/1)的序列转换为 32 位(uint32_t)?