PRIu64 is "llu" according to c9x standard. But windows doesn't understand "llu". It understands I64u, but that's non-standard.
_mingw.h has the following:
Code:
/* We are activating __USE_MINGW_ANSI_STDIO for various define indicators.
* printf ll modifier (unsupported by msvcrt.dll) is required by C99 and C++11 standards. */
#if (defined (_POSIX) || defined (_POSIX_SOURCE) || defined (_POSIX_C_SOURCE) \
|| defined (_ISOC99_SOURCE) \
|| (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && __MSVCRT_VERSION__ < 0xE00) \
|| (defined (__cplusplus) && __cplusplus >= 201103L && __MSVCRT_VERSION__ < 0xE00) \
|| defined (_XOPEN_SOURCE) || defined (_XOPEN_SOURCE_EXTENDED) \
|| defined (_GNU_SOURCE) \
|| defined (_SVID_SOURCE)) \
&& !defined(__USE_MINGW_ANSI_STDIO)
/* Enable __USE_MINGW_ANSI_STDIO if user did _not_ specify it explicitly... */
# define __USE_MINGW_ANSI_STDIO 1
#endif
inttypes.h has the following
Code:
/* 7.8.1 Macros for format specifiers
*
* MS runtime does not yet understand C9x standard "ll"
* length specifier. It appears to treat "ll" as "l".
* The non-standard I64 length specifier causes warning in GCC,
* but understood by MS runtime functions.
*/
#if defined(_UCRT) || __USE_MINGW_ANSI_STDIO
#define PRId64 "lld"
#define PRIi64 "lli"
#define PRIo64 "llo"
#define PRIu64 "llu"
#define PRIx64 "llx"
#define PRIX64 "llX"
#else
#define PRId64 "I64d"
#define PRIi64 "I64i"
#define PRIo64 "I64o"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
#endif
On a win10-2004 machine, with latest msys2 and mingw64-gcc compiler 10.2.0-3, the following code outputs "lu" instead of the number 1337.
Code:
#include <stdio.h>
#include <inttypes.h>
#include <windows.h>
int wmain(int argc, wchar_t ** argv, wchar_t **env)
{
unsigned long long a = 1337;
wchar_t str[100];
wsprintfW(str, L"%" PRIu64 "\n", a);
wprintf(str); // Prints lu, not the number
return 0;
}
The wsprintfW above results in the below call
Code:
wsprintfW(str, L"%llu", a);
Force-undefing __USE_MINGW_ANSI_STDIO causes PRIu64 to resolve to I64u.
Code:
#include <stdio.h>
#undef __USE_MINGW_ANSI_STDIO
#include <inttypes.h>
#include <windows.h>
int wmain(int argc, wchar_t ** argv, wchar_t **env)
{
unsigned long long a = 1337;
wchar_t str[100];
wsprintfW(str, L"%" PRIu64 "\n", a);
wprintf(str); // Prints 1337
return 0;
}
Compilation command
Code:
gcc -Wall -municode a.c
People ought to know their tools before using them.
Edit: I can't build usbimager's tree @ commit e216859db725 with msys2.
It gives error:
Code:
disks_win.c:33:10: fatal error: ddk/ntdddisk.h: No such file or directory
There are warnings about casting pointer to integer of difference size, and about mismatches in format specifiers.
Also, when I exposed a 100MB usb disk to the machine, usbimager wasn't able to see it unless I also created a partition on it. Then, in its device selector drop down listed the volume size as 1.0 GB, when it is merely 97 MB!
----
Edit: The older msys(1.0) defaults PRIu64 to I64u (for C code). Its inttypes.h file:
Code:
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
/* 7.8.1 Macros for format specifiers
*
* MS runtime does not yet understand C9x standard "ll"
* length specifier. It appears to treat "ll" as "l".
* The non-standard I64 length specifier causes warning in GCC,
* but understood by MS runtime functions.
*/
. . .
#define PRIu64 "I64u"
. . .
So the difference is between in the toolchains; nothing to do with gcc. But one can understand how anybody can get confused since both gcc and the toolchain were upgraded together.
---
Edit: the crash occurs because the argument that is supposed to be used with %llu is used with %s. So %llu is probably skipped by windows, and the next specifier, which happens to be %s gets paired with the integer argument meant for %llu. The argumentt is treated as an address and very likely causes crash or corruption, depending on the value.