我有一个size_t类型的变量,我想使用printf()打印它。我使用什么格式说明符来可移植地打印它?

在32位机器中,%u似乎是正确的。我用g++ -g -W -Wall -Werror -ansi -pedantic编译,没有警告。但是当我在64位机器上编译该代码时,它会产生警告。

size_t x = <something>;
printf("size = %u\n", x);

warning: format '%u' expects type 'unsigned int', 
    but argument 2 has type 'long unsigned int'

如预期的那样,如果我将其更改为%lu,警告就会消失。

问题是,我如何编写代码,使它在32位和64位机器上编译警告免费?

编辑:作为一种变通方法,我猜一个答案可能是将变量“强制转换”为一个足够大的整数,比如unsigned long,然后使用%lu打印。这在两种情况下都适用。我看看有没有其他的办法。


当前回答

对于那些在c++中不一定支持C99扩展的人来说,我衷心推荐boost::format。这使得size_t类型的大小问题没有意义:

std::cout << boost::format("Sizeof(Var) is %d\n") % sizeof(Var);

由于在boost::格式中不需要大小说明符,所以只需考虑如何显示值即可。

其他回答

使用z修饰符:

size_t x = ...;
ssize_t y = ...;
printf("%zu\n", x);  // prints as unsigned decimal
printf("%zx\n", x);  // prints as hex
printf("%zd\n", y);  // prints as signed decimal

看起来它取决于你使用的编译器(漂白):

Gnu显示%zu(或%zx,或%zd,但这显示它就像它有符号一样,等等) 微软说%Iu(或%Ix,或%Id,但同样是有符号的,等等)-但从cl v19(在Visual Studio 2015中)开始,微软支持%zu(参见对这条评论的回复)

...当然,如果你正在使用c++,你可以按照AraK的建议使用cout。

在某些平台上,对于某些类型,有特定的printf转换说明符可用,但有时必须求助于更大的类型强制转换。

我在这里用示例代码记录了这个棘手的问题: http://www.pixelbeat.org/programming/gcc/int_types/ 并定期更新有关新平台和类型的信息。

std::size_t s = 1024;
std::cout << s; // or any other kind of stream like stringstream!

如果你想打印size_t的值作为字符串,你可以这样做:

char text[] = "Lets go fishing in stead of sitting on our but !!";
size_t line = 2337200120702199116;

/* on windows I64x or I64d others %lld or %llx if it works %zd or %zx */
printf("number: %I64d\n",*(size_t*)&text);
printf("text: %s\n",*(char(*)[])&line);

结果是:

号码:2337200120702199116

我们去钓鱼吧,别坐在椅子上了!

编辑:重新阅读问题,因为向下投票,我注意到他的问题不是%llu或%I64d,而是size_t类型在不同的机器上看到这个问题https://stackoverflow.com/a/918909/1755797 http://www.cplusplus.com/reference/cstdio/printf/

Size_t在32位机器上是unsigned long long int,在64位机器上是unsigned long long int 但是%ll总是期望一个unsigned long long int。

Size_t在不同的操作系统上的长度不同,而%llu是相同的