Here's a weird one.
I copied some code from an existing embedded project to use in a quick test app on desktop. Part of that was a utility logging function that takes a format string as an argument and ultimately outputs it using
printf(). I have the header declaration of that logging function attributed with "
__attribute__((format(__printf__, 3, 0)))" so that the compiler can warn against improper format-string usage.
However, I was surprised to find that when compiling with x86_64 GCC (MinGW-w64 GCC v15.2.0, from xPack), I get format string warnings whenever I'm using "%zu": "
warning: unknown conversion type character 'z' in format".

Why does GCC suddenly not understand 'z' length modifiers in format strings when doing argument validation?
I found that changing the function attribute from "__printf__" to "__gnu_printf__" makes it understand 'z'. The GCC documentation says the following about the difference:
The parameter archetype determines how the format string is interpreted. Valid archetypes include printf, scanf, strftime, gnu_printf, gnu_scanf, gnu_strftime or strfmon. (You can also use __printf__, __scanf__, __strftime__ or __strfmon__.) archetype values such as printf refer to the formats accepted by the system’s C runtime library, while values prefixed with ‘gnu_’ always refer to the formats accepted by the GNU C Library.
I don't understand why there's a difference between the "system" C library and glibc, given that I believe both cases would actually be glibc. And anyway, 'z' length modifiers (along with
size_t) are standard since C99, so what "system" C library wouldn't support that these days? I'm also compiling with
-std=c23, so it shouldn't think I'm wanting anything prior to C99.
What's going on?
