How can one print a size_t variable portably using

2018-12-31 14:35发布

I have a variable of type size_t, and I want to print it using printf(). What format specifier do I use to print it portably?

In 32-bit machine, %u seems right. I compiled with g++ -g -W -Wall -Werror -ansi -pedantic, and there was no warning. But when I compile that code in 64-bit machine, it produces warning.

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

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

The warning goes away, as expected, if I change that to %lu.

The question is, how can I write the code, so that it compiles warning free on both 32- and 64- bit machines?

Edit: I guess one answer might be to "cast" the variable into an unsigned long, and print using %lu. That would work in both cases. I am looking if there is any other idea.

标签: c printf
12条回答
孤独寂梦人
2楼-- · 2018-12-31 14:41

For C89, use %lu and cast the value to unsigned long:

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

For C99 and later, use %zu:

size_t foo;
...
printf("foo = %zu\n", foo);
查看更多
深知你不懂我心
3楼-- · 2018-12-31 14:42

Extending on Adam Rosenfield's answer for Windows.

I tested this code with on both VS2013 Update 4 and VS2015 preview:

// test.c

#include <stdio.h>
#include <BaseTsd.h> // see the note below

int main()
{
    size_t x = 1;
    SSIZE_T y = 2;
    printf("%zu\n", x);  // prints as unsigned decimal
    printf("%zx\n", x);  // prints as hex
    printf("%zd\n", y);  // prints as signed decimal
    return 0;
}

VS2015 generated binary outputs:

1
1
2

while the one generated by VS2013 says:

zu
zx
zd

Note: ssize_t is a POSIX extension and SSIZE_T is similar thing in Windows Data Types, hence I added <BaseTsd.h> reference.

Additionally, except for the follow C99/C11 headers, all C99 headers are available in VS2015 preview:

C11 - <stdalign.h>
C11 - <stdatomic.h>
C11 - <stdnoreturn.h>
C99 - <tgmath.h>
C11 - <threads.h>

Also, C11's <uchar.h> is now included in latest preview.

For more details, see this old and the new list for standard conformance.

查看更多
旧时光的记忆
4楼-- · 2018-12-31 14:46
std::size_t s = 1024;
std::cout << s; // or any other kind of stream like stringstream!
查看更多
余生无你
5楼-- · 2018-12-31 14:49

On some platforms and for some types there are specific printf conversion specifiers available, but sometimes one has to resort to casting to larger types.

I've documented this tricky issue here, with example code: http://www.pixelbeat.org/programming/gcc/int_types/ and update it periodically with info on new platforms and types.

查看更多
栀子花@的思念
6楼-- · 2018-12-31 14:54

if you want to print the value of a size_t as a string you can do this:

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);

result is:

number: 2337200120702199116

text: Lets go fishing in stead of sitting on our but !!

Edit: rereading the question because of the down votes i noted his problem is not %llu or %I64d but the size_t type on different machines see this question https://stackoverflow.com/a/918909/1755797
http://www.cplusplus.com/reference/cstdio/printf/

size_t is unsigned int on a 32bit machine and unsigned long long int on 64bit
but %ll always expects a unsigned long long int.

size_t varies in length on different operating systems while %llu is the same

查看更多
回忆,回不去的记忆
7楼-- · 2018-12-31 15:00

Looks like it varies depending on what compiler you're using (blech):

...and of course, if you're using C++, you can use cout instead as suggested by AraK.

查看更多
登录 后发表回答