I know this has been questioned many times on SO, but my problem is specific to ANSI C (C89).
In C99 there are the sub-specifiers z
and t
, which are not supported in ANSI C.
What about using the p
specifier?
size_t
is an implementation-defined unsigned integer type. ptrdiff_t
is an implementation-defined signed integer type.
In C89/C90 (commonly, but strictly speaking incorrectly, referred to as "ANSI C"), there are no special format specifiers for these types. But the widest integer types are long int
and unsigned long int
, which of course do have their own format specifiers.
To print a size_t
value, cast it to unsigned long
and use "%lu"
.
To print a ptrdiff_t
value, cast it to long
and use "%ld"
.
Note that if your code is then compiled with a C99 or C11 compiler, it's possible that size_t
and/or ptrdiff_t
could be wider than long
, and the code could fail. (As I recall the 64-bit Windows interface has 32-bit long
, so that could be an issue in practice.)
In C99 and later, just use %zu
for size_t
and %td
for ptrdiff_t
. If you want your code to be really portable, consider using #if
to test the value of __STDC_VERSION__
.
You could also run into problems if you have a compiler that only partially conforms to C99 or C11. You might have a compiler that doesn't fully support C99, but that does provide long long
. But for the purpose of printing a size_t
value, that's only going to be an issue if the value you're printing actually exceeds ULONG_MAX
, which is at least 232-1. For a ptrdiff_t
value, converting to long
is OK as long as it doesn't exceed LONG_MAX
, which is at least 231-1.
Finally, if you happen to know that the values you're printing aren't too big, you can get away with casting to int
and using %d
. I recommend casting to unsigned long
or long
, but int
is OK for quick-and-dirty code.
What about using the
p
specifier?
No, %p
is only for pointers of type void*
, and in any case the output format is implementation-defined (it's commonly hex, but I've seen other representations).