Author Topic: Why does GCC's 'format' function attribute no longer think '%zu' is valid?  (Read 2303 times)

0 Members and 6 Guests are viewing this topic.

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1922
  • Country: gb
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:

Quote
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? :-//
 

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 2254
  • Country: ua
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #1 on: February 13, 2026, 05:36:31 pm »
What does the printf() documentation for your system's standard C library say?
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 4841
  • Country: us
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #2 on: February 13, 2026, 05:43:53 pm »
Maybe it thinks the "system" libc is an old enough version Microsoft libc that it doesn't support %zu?
 
The following users thanked this post: 5U4GB

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1922
  • Country: gb
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #3 on: February 13, 2026, 06:33:21 pm »
How can I tell what it thinks the "system" C library is?

Windows doesn't really have the concept of a system standard C library. There is the sort-of de-facto 'standard' C library of the Visual C++ runtime, which is either statically or dynamically linked, but as far as I'm aware only applications compiled with Visual C++ use that. Would MinGW-w64 GCC link against msvcrt rather than glibc? If it does, Visual C++ runtime printf supports the 'z' length modifier, and has done for a long time. So why would GCC think it doesn't?
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17788
  • Country: fr
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #4 on: February 13, 2026, 07:55:06 pm »
The 'z' printf format is non-standard AFAIK so you can unfortunately not count on it for any kind of portable code.
If you're compiling for Windows, AFAIR 'z' is definitely not supported by the MS standard C library (msvcrt.dll IIRC), which I think is what mingw compilers link against by default.

For more portable printf formats, I recommend using the macros defined in inttypes.h, even though that makes your format strings clunkier to write and read.

There is unfortunately not (that I know of anyway) a macro for the 'size_t' type, but your best bet may be to use the PRIuMAX macro for that.

So instead of printf("%zu", n) you would have something like printf("%" PRIuMAX, n);
Yes, a bit clunkier, but more portable.
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 2692
  • Country: au
    • Halestrom
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #5 on: February 13, 2026, 08:22:40 pm »
Does it still complain if you add -std=gnu18 or -std=gnu99 to the args?  Perhaps your gcc build is defaulting to an ISO C standard instead of a version with GNU extensions.
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1830
  • Country: de
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #6 on: February 13, 2026, 08:34:27 pm »
The 'z' printf format is non-standard AFAIK so you can unfortunately not count on it for any kind of portable code.

IMO it is C99.

Quote
If you're compiling for Windows, AFAIR 'z' is definitely not supported by the MS standard C library (msvcrt.dll IIRC), which I think is what mingw compilers link against by default.

I think MS introduced it with VS 2015 -> Universal C Runtime (ucrtbase.dll).
There should exist a MinGW variant based on UCRT.
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1922
  • Country: gb
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #7 on: February 13, 2026, 08:38:20 pm »
The 'z' printf format is non-standard AFAIK so you can unfortunately not count on it for any kind of portable code.

I'm talking about the 'z' length modifier, not format specifier - that is, using 'z' as a prefix for things like %u or %x (e.g. "%zu"), no different from 'h', 'l', or 'll'. And the 'z' length modifier is standard as of C99.

If you're compiling for Windows, AFAIR 'z' is definitely not supported by the MS standard C library (msvcrt.dll IIRC), which I think is what mingw compilers link against by default.

Okay, so if MinGW does link against msvcrt, then yes, 'z' length modifier is supported, and has been for over a decade now: https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-140#size

Does it still complain if you add -std=gnu18 or -std=gnu99 to the args?  Perhaps your gcc build is defaulting to an ISO C standard instead of a version with GNU extensions.

I tried with -std=gnu23 instead of -std=c23 and it still complains.
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1830
  • Country: de
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #8 on: February 13, 2026, 09:09:03 pm »
Okay, so if MinGW does link against msvcrt, then yes, 'z' length modifier is supported,

No, I think it was never supported in msvcrt.dll.

Quote
and has been for over a decade now: https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-140#size

You refer to the docs of VS 2015 which does no longer use msvcrt.dll, but introduced a new "Universal C Runtime" (ucrtbase.dll).
Maybe you want to try the UCRT-based MinGW toochain (mingw-w64-ucrt-x86_64)?
« Last Edit: February 13, 2026, 09:13:35 pm by gf »
 
The following users thanked this post: SiliconWizard

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1922
  • Country: gb
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #9 on: February 13, 2026, 09:53:29 pm »
Okay, it took a bit of digging, because it wasn't obvious, but I've found that the xPack GCC I'm using ("gcc (xPack MinGW-w64 GCC x86_64) 15.2.0)") is linking against the Universal C Runtime:

Code: [Select]
objdump -p my_app.exe | find "DLL Name"
        DLL Name: KERNEL32.dll
        DLL Name: api-ms-win-crt-environment-l1-1-0.dll
        DLL Name: api-ms-win-crt-heap-l1-1-0.dll
        DLL Name: api-ms-win-crt-locale-l1-1-0.dll
        DLL Name: api-ms-win-crt-math-l1-1-0.dll
        DLL Name: api-ms-win-crt-private-l1-1-0.dll
        DLL Name: api-ms-win-crt-runtime-l1-1-0.dll
        DLL Name: api-ms-win-crt-stdio-l1-1-0.dll
        DLL Name: api-ms-win-crt-string-l1-1-0.dll

By the way, I can confirm without doubt that '%zu' actually works, because I'm using it in other code - not just the logging function I copied from elsewhere:

Code: [Select]
size_t bytes_read = fread(buffer, 1, file_size, file);
/* ... */
printf("---- File: %s (%zu bytes) ----\n", filename, bytes_read);

Gives output:

Code: [Select]
---- File: blah.bin (52 bytes) ----

So the question still remains: why the heck is it just GCC's format string argument validation that doesn't think the underlying C library printf supports 'z' length modifier, when it very much does? :-//
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 8061
  • Country: pl
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #10 on: February 13, 2026, 10:45:33 pm »
If the format checker complains about a standard feature which is even supported by the implementation maybe you should just report it as a bug to wherever you got this software from.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17788
  • Country: fr
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #11 on: February 13, 2026, 11:21:30 pm »
The 'z' printf format is non-standard AFAIK so you can unfortunately not count on it for any kind of portable code.

IMO it is C99.

Right, just checked. I have been assuming it being non-standard for a long time but the reality was it was just unsupported by MS for a long time, which was making it unfortunately non-portable unless you didn't care about Windows.

The bottom line was that MS had ignored C99 for an extraordinary long time.

Quote
If you're compiling for Windows, AFAIR 'z' is definitely not supported by the MS standard C library (msvcrt.dll IIRC), which I think is what mingw compilers link against by default.

I think MS introduced it with VS 2015 -> Universal C Runtime (ucrtbase.dll).
There should exist a MinGW variant based on UCRT.

Possibly, never used that myself because I was used to sticking to what was supported by msvcrt (which was your best bet if you wanted to maximize your compatibility odds on Windows). It seems supported on Windows 7, for instance, only via an additional update. msvcrt is available out of the box on all Windows.

I would personally not bother going through hoops for using ucrt with mingw (and possibly annoy Windows 7 users that wouldn't necessarily have ucrt support) just to get support for the 'z' format modifier, but to each their own.
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1830
  • Country: de
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #12 on: February 14, 2026, 12:08:29 am »
So the question still remains: why the heck is it just GCC's format string argument validation that doesn't think the underlying C library printf supports 'z' length modifier, when it very much does? :-//

I'm not sure, but maybe -D__USE_MINGW_ANSI_STDIO=1 helps.
However, my understanding is that it replaces Microsoft's formatting functions with MinGW's own ones.
So under the hood, you don't call msvcrt's or UCRT's printf() any more, but MinGW's own printf().
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1922
  • Country: gb
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #13 on: February 14, 2026, 06:20:30 pm »
I'm not sure, but maybe -D__USE_MINGW_ANSI_STDIO=1 helps.

Tried and it didn't help. :(

It seems there is a disconnect between how GCC is validating format string arguments, and the actual printf implementation in use - GCC obviously doesn't think the capabilities of the library implementation are what they are.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2175
  • Country: fi
  • Embedded SW/HW.
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #14 on: February 14, 2026, 07:52:12 pm »
Have you tried https://godbolt.org/ for checking how different C compilers behave with the %zu format directive?
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: Why does GCC's 'format' function attribute no longer think '%zu' is valid?
« Reply #15 on: February 20, 2026, 06:10:59 pm »
What's going on? :-//

It simply means that your version of the compiler is somehow unaware of `%zu`. The library probably supports it, but the attributes are checked by the compiler itself, regardless of what the library supports.

Why and how your GCC 15 (!) is unaware of `%zu` is completely unclear.

"__attribute__((format(__printf__, 3, 0)))" so that the compiler can warn against improper format-string usage.

Zero as the last attribute argument means that the arguments will not be available for checking. So, the compiler will simply check the format string for overall correctness but will not try to match the format specifiers to the arguments. Could this weird behavior somehow be triggered specifically by `0` as the third argument of this attribute? If you try a more conventional example with non-zero third argument, does it still complain about `%zu`?

(I could not reproduce it in my experiments with GCC 15.2 on Godbolt.)
« Last Edit: February 20, 2026, 07:09:55 pm by TheCalligrapher »
 

Offline Alien Brother

  • Regular Contributor
  • *
  • Posts: 68
  • Country: fr
If I recall correctly, these warnings are valid in the case when you build for Windows XP and will call into its msvcrt.dll; I don't think they are supposed to appear in the UCRT version of MinGW. I'd think it's a bug in that particular distribution of MinGW.
« Last Edit: March 19, 2026, 03:14:16 am by Alien Brother »
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 8349
  • Country: fi
    • My home page and email address
Why does GCC suddenly not understand 'z' length modifiers in format strings when doing argument validation?
It's because your target is MingW, per gcc-15.2.0/gcc/config/mingw/msformat-c.cc:ms_printf_length_specs[].

As you have already noted, you can use ms_printf for that prototype, and gnu_printf for the one you expect.

Note that all printf family functions are implemented as GCC built-ins (as if you used e.g. __builtin_printf() instead of printf()) so it can at compile time optimize e.g. printf() call without any conversions and ending with a newline as a call to puts().  If you want to omit this, you can use gcc command line option -fno-builtin-printf, in which case GCC will not check the formatting either (because the standard library header include files do not have the needed format GCC attribute).
 
The following users thanked this post: SiliconWizard


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->