gnu::format(3attr)

πŸ’… gnu::format β€” the vibe check for your format strings

okay bestie, gather round, because this one is a GCC/Clang attribute and she is iconic. This is gnu::format from the 3attr manual, and she's here to make sure your format strings don't embarrass you in production. πŸŽ€


✨ NAME ✨

gnu::format β€” the attribute that says "hey, this parameter? it's a format string, and I have opinions about its style" πŸ¦‹


🌸 SYNOPSIS 🌸

[[gnu::format(style, fmt-idx, first-idx)]]

πŸ’– DESCRIPTION πŸ’–

So basically, this attribute gets slapped onto a function. What it does is declare that one of the function's parameters is a format string, and it also tells the compiler which style of format string it is. Why do we care? Because then the compiler can vibe check two things for you:

  • the syntax of the format string itself
  • the types of all the variadic arguments you're passing in

No cap, it catches a whole category of bugs before you even run the thing.

The style can be one of these four, and honestly, pick wisely:

  • printf
  • scanf
  • strftime
  • strfmon

Now, fmt-idx is a 1-based index that tells everyone where the format string sits in the parameter list. Count like a human, not like a programmer. πŸ’…

And first-idx is a 1-based index pointing at the first argument that corresponds to the format string. But listen, important plot twist: if that first argument is part of a va_list argument, you pass 0 instead. Not 1. Zero. Remember that, bestie, it's a jumpscare every time. 😭


🌈 VERSIONS 🌈

🧚 GNU syntax

__attribute__((format(style, fmt-idx, first-idx)))

⭐ Styles

On some targets, other styles are additionally supported. So you're not stuck with just the four classics β€” depends where you're compiling, iykyk.

πŸ’€ MinGW

πŸ’€ Microsoft Windows

  • ms_printf
  • ms_scanf
  • ms_strftime

These correspond to the formats supported by the msvcrt.dll library. So if you're on Windows-flavoured toolchains, these are your girls.

GCC-only. πŸ‘‘

🌞 Solaris

  • cmn_err

🍎 Darwin

  • CFString

🐑 OpenBSD

  • kprintf
  • syslog
  • syslog is Clang-only.

😈 FreeBSD

  • freebsd_kprintf β€” Clang-only.

And it's not just C-like languages getting in on this, okay? In some languages, other styles are additionally supported too. Main character energy across the board.

πŸ’œ Objective-C

  • NSString

🫢 Non-variadic functions

Clang accepts the attribute on non-variadic functions as an extension. So like, it's flexible. She contains multitudes.


πŸ‘‘ STANDARDS πŸ‘‘

GNU. That's it. That's the standard. πŸ“œ


πŸ•°οΈ HISTORY πŸ•°οΈ

  • gcc
  • g++
  • clang 2.8
  • clang++ 2.8

Ancient history, but still serving. ✨


πŸ“ EXAMPLES πŸ“

Okay here's the good stuff, actual code, look at her:

[[gnu::format(printf, 3, 0)]]
int
vstprintf(int size;
    char buf[restrict size], int size,
    const char *restrict fmt, va_list args)
{
     int len;

     if (size == 0) {
          errno = EOVERFLOW;
          return -1;
     }

     len = vsnprintf(buf, size, fmt, args);
     if (len >= size) {
          errno = E2BIG;
          return -1;
     }

     return len;
}

See how first-idx is 0 there? That's the va_list situation I told you about. Told you. 😌

[[gnu::format(printf, 3, 4)]]
int
stprintf(int size;
    char buf[restrict size], int size,
    const char *restrict fmt, ...)
{
     int len;
     va_list args;

     va_start(args, fmt);
     len = vstprintf(buf, size, fmt, args);
     va_end(args);

     return len;
}

And here first-idx is 4, because the first vararg lines up with the format string. Periodt. πŸ’…


fr fr, if you skip the first-idx rule for va_list args, your compiler warnings will be lying to you and that's the worst kind of betrayal. πŸ™ˆ

okay that's the whole page, bestie, you ate it UP 🫢 This was gnu::format(3attr) from Linux man-pages 6.20, dated 2025-09-25 β€” love her, stan her, go annotate all your wrapper functions. πŸŒΈπŸ’–βœ¨

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms