Cross platform format string for variables of type size_t? [duplicate]

Solution 1:

The PRIuPTR macro (from <inttypes.h>) defines a decimal format for uintptr_t, which should always be large enough that you can cast a size_t to it without truncating, e.g.

fprintf(stream, "Your size_t var has value %" PRIuPTR ".", (uintptr_t) your_var);

Solution 2:

There are really two questions here. The first question is what the correct printf specifier string for the three platforms is. Note that size_t is an unsigned type.

On Windows, use "%Iu".

On Linux and OSX, use "%zu".

The second question is how to support multiple platforms, given that things like format strings might be different on each platform. As other people have pointed out, using #ifdef gets ugly quickly.

Instead, write a separate makefile or project file for each target platform. Then refer to the specifier by some macro name in your source files, defining the macro appropriately in each makefile. In particular, both GCC and Visual Studio accept a 'D' switch to define macros on the command line.

If your build system is very complicated (multiple build options, generated sources, etc.), maintaining 3 separate makefiles might get unwieldly, and you are going to have to use some kind of advanced build system like CMake or the GNU autotools. But the basic principle is the same-- use the build system to define platform-specific macros instead of putting platform-detection logic in your source files.

Solution 3:

The only thing I can think of, is the typical:

#ifdef __WIN32__ // or whatever
#define SSIZET_FMT "%ld"
#else
#define SSIZET_FMT "%zd"
#endif

and then taking advantage of constant folding:

fprintf(stream, "Your size_t var has value " SSIZET_FMT ".", your_var);

Solution 4:

Dan Saks wrote an article in Embedded Systems Design which covered this matter. According to Dan, %zu is the standard way, but few compilers supported this. As an alternative, he recommended using %lu together with an explicit cast of the argument to unsigned long:

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