I am using the mingw-w64 (x64) fork of minGW as prepared on nuwen.net. This is from the 7.1 version of gcc :
gcc --version
gcc (GCC) 7.1.0
The alternative solution as mentioned in comments is to toss in the __USE_MINGW_ANSI_STDIO
compiler switch:
#define __USE_MINGW_ANSI_STDIO 1
#include <stdio.h>
int main(void)
{
size_t a = 100;
printf("a=%lu\n",a);
printf("a=%llu\n",a);
printf("a=%zu\n",a);
printf("a=%I64u\n",a);
}
This makes the code compile as expected and gcc now gives the appropriate warnings:
warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t' [-Wformat=]
warning: ISO C does not support the 'I' printf flag [-Wformat=]
warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'size_t' [-Wformat=]
Alternatively you can define the macro on command line with -D__USE_MINGW_ANSI_STDIO=1
The problem is not the compiler but the C library. MinGW uses Microsoft's "Visual C Runtime" (msvcrt
) which only conforms to c89 and it doesn't support the z
format specifier.
Here's what you can do to safely print a size_t
when using MinGW:
#include <inttypes.h>
#include <stdio.h>
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
# else
# define PRI_SIZET PRIu32
# endif
#else
# define PRI_SIZET "zu"
#endif
int main(void)
{
size_t mySize = 24;
printf("%" PRI_SIZET "\n", mySize);
}
On win64, you would get a warning with this code, because PRIu64
expands to the msvcrt
-specific I64u
format specifier. But you can silence this warning with the GCC flag -Wno-pedantic-ms-format
.
Note that you need a similar trick for long long
(here using PRIu64
on both 32bit and 64bit windows) because msvcrt
doesn't know ll
either.
edit: as pointed out by @M.M in a comment, you can instead link MinGW-provided alternative stdio
functions that support C11 with #define __USE_MINGW_ANSI_STDIO 1
. I prefer not to link extra code if I can get around the peculiarities of msvcrt
, but that's of course a matter of taste.
PRIuPTR
trick works (Cross platform format string for variables of type size_t?):
#include <stdio.h>
#include <inttypes.h>
int main()
{
size_t a = (size_t)(1024ULL * 1024 * 1024 * 1024 + 13);
printf("a = %" PRIuPTR "\n", a);
printf("sizeof(size_t) = %" PRIuPTR "\n", sizeof(size_t));
printf("sizeof(uintptr_t) = %" PRIuPTR "\n", sizeof(uintptr_t));
return 0;
}
Output x86:
a = 13
sizeof(size_t) = 4
sizeof(uintptr_t) = 4
Output x64:
a = 1099511627789
sizeof(size_t) = 8
sizeof(uintptr_t) = 8