How can one print a size_t variable portably using the printf family?

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

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

  • gnu says %zu (or %zx, or %zd but that displays it as though it were signed, etc.)
  • Microsoft says %Iu (or %Ix, or %Id but again that's signed, etc.) — but as of cl v19 (in Visual Studio 2015), Microsoft supports %zu (see this reply to this comment)

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


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

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.

Tags:

C

Printf