As printf()
is part of the C standard library, it is typically implemented in some runtime library. When this is linked dynamically, it's possible to have such effects with the same code, if, depending on which Process calls the code, a different version of the library is linked. If %zu
doesn't work, it's an old version that doesn't support C99 yet.
On windows, it's quite probably the system's MSVCRT.DLL, that's not intended for public usage any more, but is kept compatible to the old MS Visual C 6 version. For example MinGW by default links to that library, so you don't need to ship your own C runtime. This of course has the drawback to limit the library functions to C89/C90.
An often reasonably safe thing to do for printing a size_t
is to convert it to an unsigned long
and print that:
size_t x = 666;
printf("x=%lu", (unsigned long)x);
This would only give wrong results if
- the platform actually has a larger
size_t
than unsigned long
(this is true e.g. for a 64bit system with LLP64 data model like, unfortunately, win64) and
- you really have a size at runtime that doesn't fit in the
unsigned long
. This would have to be at least a value larger than 4G (232) as this is the guaranteed minimum range for unsigned long
.
Please note that the cast is very important here. Because printf()
is a variadic function, the prototype just looks like printf(const char *fmt, ...)
, so there's no type information for the compiler available -- therefore automatic conversions are not possible.
If the problem is specifically MSVCRT.DLL and you want to stick to C99 or later in general, I suggested a method using inttypes.h
in an earlier answer. This will never print a wrong value on Windows (and still require a C99-conforming standard library on other platforms).