fmtlib Standard Format Specifiers: Complete Reference for printf-Style Syntax
The {fmt} library supports twelve core conversion specifiers—d/i/u, o, x/X, f/F, e/E, g/G, a/A, c, s, and p—that map to internal presentation types defined in include/fmt/printf.h.
The {fmt} library provides a high-performance formatting implementation compatible with both modern {}-style formatting and traditional C printf-style syntax. Understanding the standard format specifiers available in fmtlib helps developers write portable, efficient formatting code. The specifier parsing logic resides primarily in include/fmt/printf.h, where the parse_printf_presentation_type function converts each format character into an internal presentation type.
Integer Format Specifiers in fmtlib
The integer format specifiers in fmtlib format specifiers follow standard C conventions with full signed and unsigned support.
Decimal and Unsigned Integers
d/i— signed decimal integer, maps to internaldecpresentation typeu— unsigned decimal integer, also maps todec
fmt::printf("%d", -42); // → -42
fmt::printf("%i", 42); // → 42
fmt::printf("%u", 42); // → 42
Octal and Hexadecimal Integers
o— octal integer, maps to internaloctpresentation typex— hexadecimal integer (lowercase), maps tohexX— hexadecimal integer (uppercase), maps tohex
fmt::printf("%o", 10); // → 12
fmt::printf("%08x", 255); // → 000000ff
fmt::printf("%#X", 255); // → 0XFF
Floating-Point Format Specifiers in fmtlib
fmtlib floating-point specifiers provide four distinct presentation modes for real numbers.
Fixed and Scientific Notation
f/F— fixed-point notation, maps to internalfixedpresentation typee/E— scientific (exponential) notation, maps toexp
fmt::printf("%f", 3.14159); // → 3.141590
fmt::printf("%+.2e", 0.001); // → +1.00e-03
fmt::printf("%E", 1234.5); // → 1.234500E+03
General and Hexadecimal Formats
g/G— general format (chooses fixed or scientific based on magnitude), maps togenerala/A— hexadecimal floating-point, maps tohexfloat
fmt::printf("%g", 123456.0); // → 123456
fmt::printf("%.2g", 123456.0); // → 1.2e+05
fmt::printf("%a", 3.14159); // → 0x1.921f9f01b866ep+1
Character, String, and Pointer Specifiers
Single Character and Strings
c— character (integral value converted to character), maps to internalchrs— string (C-string orbasic_string_view), maps tostring
fmt::printf("%c", 65); // → A
fmt::printf("%s", "hello"); // → hello
fmt::printf("%.3s", "hello"); // → hel
Pointer Address
p— pointer address, maps to internalpointer
int x = 42;
fmt::printf("%p", &x); // → 0x7ff… (platform-dependent address)
Length Modifiers in fmtlib Format Specifiers
Beyond conversion characters, fmtlib standard format specifiers support standard C length modifiers that adapt argument types. These are processed in the vprintf function around line 1050 of include/fmt/printf.h.
| Modifier | Meaning |
|---|---|
hh |
signed/unsigned char |
h |
signed/unsigned short |
l |
long / wchar_t |
ll |
long long |
j |
intmax_t / uintmax_t |
z |
size_t |
t |
ptrdiff_t |
L |
long double |
fmt::printf("%lld", 9223372036854775807LL); // long long
fmt::printf("%zu", sizeof(int)); // size_t
fmt::printf("%Lf", 3.14159265358979323846L); // long double
Source Implementation Details
The fmtlib format specifier mapping is implemented in the parse_printf_presentation_type function within include/fmt/printf.h (around line 86). This function uses a switch statement on the conversion character to return the appropriate internal presentation type enum value.
For the modern {}-style formatting API, include/fmt/format.h provides the higher-level interface through fmt::format, fmt::print, and related functions. Both APIs ultimately resolve to the same underlying formatting engine.
The printf-style implementation is header-only; no separate src/printf.cc file exists for runtime helpers.
Summary
- fmtlib implements twelve core printf-style format specifiers:
d/i/u,o,x/X,f/F,e/E,g/G,a/A,c,s, andp - The
parse_printf_presentation_typefunction ininclude/fmt/printf.h(line ~86) maps each specifier to internal presentation types - Standard C length modifiers (
hh,h,l,ll,j,z,t,L) are fully supported - Both
printf.handformat.hprovide APIs that resolve to the same formatting engine - Implementation is header-only with no separate compilation unit required
Frequently Asked Questions
What is the difference between %d and %i in fmtlib?
There is no functional difference between %d and %i in fmtlib—both map to the internal dec presentation type for signed decimal integers. This matches standard C behavior where both specifiers produce identical output.
Does fmtlib support the %n specifier for write-back?
No, fmtlib standard format specifiers intentionally exclude %n due to security considerations. The {fmt} documentation notes that this specifier, which writes the number of characters printed back to an argument, is not implemented to prevent format string vulnerabilities.
How do I print a bool as true/false instead of 1/0 in fmtlib?
Use the modern {}-style formatting API from include/fmt/format.h instead of printf-style specifiers. The fmt::format function automatically renders bool values as "true" or "false":
fmt::format("{}", true); // → "true"
fmt::format("{}", false); // → "false"
Printf-style %d will print 1 or 0 since bool promotes to int.
Can I use fmtlib format specifiers with std::ostream?
Yes, fmt/format.h provides fmt::print and fmt::format_to functions that write to arbitrary output iterators, including std::ostreambuf_iterator. For direct std::ostream integration, use fmt::ostream or the <fmt/ostream.h> header which provides automatic operator<< integration for fmt-formatted types.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →