uint32_t和size_t的printf格式说明符

ant*_*009 96 c printf

我有以下内容

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);
Run Code Online (Sandbox Code Playgroud)

编译时我收到以下警告:

format ‘%lu’ expects type ‘long unsigned int’, but argument has type ‘uint32_t’
Run Code Online (Sandbox Code Playgroud)

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

Format argument 1 to printf (%u) expects unsigned int gets size_t: k
Run Code Online (Sandbox Code Playgroud)

非常感谢任何建议,

ken*_*ytm 127

尝试

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);
Run Code Online (Sandbox Code Playgroud)

z代表长度相同的整数size_t,和PRIu32宏,在C99标头中定义inttypes.h,表示一个无符号的32位整数.

  • 这是正确的答案.虽然我的个人建议是简单的演员,例如`printf("%lu",(unsigned long)i)`.否则,由于类型更改,最终会在代码中出现大量警告. (7认同)
  • @alcor是的,他确实把C89(显然是他正在使用的gcc编译器标志)但他使用的是`uint32_t`,所以实际上它是C99代码,应该这样编译. (7认同)
  • @robUK:嘿.我建议你为夹板提出一个bug. (3认同)

Cog*_*eel 25

当它实际上是(32位)时,听起来你期望size_tunsigned long(可能是64位)相同unsigned int.尝试%zu在两种情况下使用.

我不完全确定.

  • -1,抱歉它不便携.所需要的只是格式说明符和类型一致,你总是可以强制转换为真.long至少是32位,所以`%lu`和`(unsigned long)k`总是正确的.`size_t`比较棘手,这就是在C99中添加`%zu`的原因.如果你不能使用它,那就把它当作`k`来处理(`long`是C89中最大的类型,`size_t`不太可能更大). (4认同)
  • 夹板实际上正在做正确的事情.只是因为你的编译器/平台上的`int32_t`恰好是`int`并不意味着它可能不会在另一个上变长.对于`size_t`也是如此.实际上它正在走出困境并做更多工作来检测这种可移植性错误,因为简单,自然的检查就是像编译器一样尊重typedef. (3认同)

u0b*_*6ae 23

所需要的只是格式说明符和类型一致,你总是可以强制转换为真.long是至少32位,所以%lu连同(unsigned long)k总是正确的:

uint32_t k;
printf("%lu\n", (unsigned long)k);
Run Code Online (Sandbox Code Playgroud)

size_t更棘手,这就是为什么%zu在C99中添加的原因.如果你不能使用它,那就对待它k(long是C89中最大的类型,size_t不太可能更大).

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

如果没有为你传递的类型提供正确的格式说明符,那么printf将相当于从数组中读取太多或太少的内存.只要您使用显式强制转换来匹配类型,它就是可移植的.


R..*_*R.. 16

如果您不想使用PRI*宏,则另一种打印ANY整数类型的方法是分别转换为intmax_tuintmax_t使用"%jd"%ju.例如,这对于没有定义PRI*宏的POSIX(或其他OS)类型特别有用off_t.