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 ma
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);
printf("size = %zu\n", sizeof(thing) );
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.
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.
C99 defines "%zd" etc. for that. (thanks to the commenters) There is no portable format specifier for that in C++ - you could use %p
, which woulkd word in these two scenarios, but isn't a portable choice either, and gives the value in hex.
Alternatively, use some streaming (e.g. stringstream) or a safe printf replacement such as Boost Format. I understand that this advice is only of limited use (and does require C++). (We've used a similar approach fitted for our needs when implementing unicode support.)
The fundamental problem for C is that printf using an ellipsis is unsafe by design - it needs to determine the additional argument's size from the known arguments, so it can't be fixed to support "whatever you got". So unless your compiler implement some proprietary extensions, you are out of luck.
Use the z
modifier:
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