uint32_t和size_t的printf格式说明符


101

我有以下

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

非常感谢您的任何建议,


2
C89不支持uint32_t<stdint.h><inttypes.h>; 如果要使用这些类型,则应升级到C89。作为扩展,GCC可能允许您使用它们,但是C89没有任何此类支持。
乔纳森·莱夫勒

10
官方的C99格式修饰符size_t是'z',如中所示"%zu"
乔纳森·勒夫勒


我相信@kenny的答案最适合uint32_t,但没有size_t。@ u0b34a0f6ae的答案包括两者。
jww

乔纳森·莱夫勒(Jonathan Leffler)在第一条评论中第二次提及C89应该是C99
bph

Answers:


28

听起来像您期望size_tunsigned long实际为unsigned int32位(可能为64位)相同。%zu两种情况下都尝试使用。

我还不确定。


1
编译时无警告。但是,运行夹板时,我得到以下信息:1)printf(%u)期望unsigned int获得uint32_t:i 2)printf(%u)期望unsigned int获得size_t:k
ant2009

听起来好像夹板只是在做书呆子。它可能偏离了源代码中的类型名称,并且没有意识到它们是等效的。我不知道该如何处理@KennyTM的答案……它肯定应该更具可移植性。
齿轮

3
夹板实际上是在做正确的事。仅因为int32_t碰巧int在您的编译器/平台上并不意味着它可能不在long另一个上。相同size_t。实际上,它不费吹灰之力,需要做更多的工作来检测此可移植性错误,因为简单而自然的检查就是像编译器一样尊重typedef。
R .. GitHub停止帮助ICE,2010年

4
-1,抱歉,它不是便携式的。所需要的只是格式说明符和类型一致,并且您可以随时进行强制转换以实现这一点。long至少为32位,因此%lu(unsigned long)k总是正确的。size_t比较棘手,这就是为什么%zu在C99中添加了它。如果您不能使用它,请像对待它一样k(它long是C89中最大的类型,size_t不太可能更大)。
u0b34a0f6ae 2011年

139

尝试

#include <inttypes.h>
...

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

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


3
@robUK:嘿。我建议您提交夹板错误。
kennytm 2010年

8
这是正确的答案。尽管我个人的建议是简单地投射,例如printf( "%lu", (unsigned long )i )。否则,由于类型更改,以后在整个代码中都会出现一堆警告。
Dummy00001

1
这是正确的答案。我同意KennyTM提出的夹板错误。顺便说一句,“%zu”是size_t的正确格式。您不需要任何PRI *宏即可打印size_t。
R .. GitHub停止帮助ICE,2010年

1
如果我没记错的话,%zu是C99,在问题中他写了“ C89”。
alcor

8
@alcor是的,他确实放了C89(显然是他正在使用的gcc编译器标志),但是他正在使用的uint32_t实际上是C99代码,应该这样编译。
Colin D Bennett

28

所需要的只是格式说明符和类型一致,并且您可以随时进行强制转换以实现这一点。long至少为32位,因此%lu(unsigned long)k总是正确的:

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

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 */

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


17

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.