我有一个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打印。这在两种情况下都适用。我看看有没有其他的办法。


当前回答

如果您传递一个32位无符号整数为%lu格式,它会警告您吗?这应该没问题,因为转换是定义良好的,不会丢失任何信息。

我听说有些平台在<inttypes.h>中定义了宏,可以插入到格式字符串文字中,但我在Windows c++编译器上没有看到这个头,这意味着它可能不是跨平台的。

其他回答

对于C89,使用%lu并将值转换为unsigned long:

size_t foo;
...
printf("foo = %lu\n", (unsigned long) foo);

对于C99及以后版本,使用%zu:

size_t foo;
...
printf("foo = %zu\n", foo);

C99为此定义了“%zd”等。c++中没有可移植的格式说明符——你可以使用%p,这在这两种情况下都是word,但也不是一个可移植的选择,并以十六进制给出值。

或者,使用一些流(例如stringstream)或安全的printf替代品,如Boost Format。我知道这个建议只有有限的用途(并且确实需要c++)。(在实现unicode支持时,我们使用了适合我们需求的类似方法。)

C语言的基本问题是printf使用省省号在设计上是不安全的——它需要从已知参数中确定额外参数的大小,所以它不能被修复为支持“你得到的任何东西”。所以除非你的编译器实现了一些专有的扩展,否则你就不走运了。

如果你想打印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是相同的

printf("size = %zu\n", sizeof(thing) );

如果您传递一个32位无符号整数为%lu格式,它会警告您吗?这应该没问题,因为转换是定义良好的,不会丢失任何信息。

我听说有些平台在<inttypes.h>中定义了宏,可以插入到格式字符串文字中,但我在Windows c++编译器上没有看到这个头,这意味着它可能不是跨平台的。