How to Format Binary Integers with fmtlib: A Complete Guide to Binary Formatting in C++
Yes, {fmt} supports binary integer formatting natively using the b or B format specifier, which converts any integral type to its base-2 representation with full control over width, alignment, and prefix.
Binary formatting is a built-in capability of the {fmt} library, implemented directly in its core formatting engine. This guide covers how to use binary specifiers, the internal implementation, and practical examples drawn from the official source code.
Binary Format Specifiers
{fmt} recognizes b (lowercase) and B (uppercase) as presentation types for binary output. In include/fmt/base.h, the library defines presentation_type::bin to represent this formatting mode (lines 1548–1566). The parser in include/fmt/format.h handles the 'b' case during format string analysis, routing integer arguments through the binary conversion path.
The binary formatter supports the same modifiers as other numeric types:
#— alternate form, prepends0bto the output- width — minimum field width for padding
- fill/alignment — left (
<), right (>), or center (^) alignment with custom fill characters - sign — plus (
+), minus (-), or space () for signed types
Basic Binary Formatting Examples
The following code demonstrates core binary formatting patterns:
#include <fmt/format.h>
#include <iostream>
int main() {
int v = 42;
// Simple binary output
std::cout << fmt::format("{:b}\n", v); // 101010
// Upper-case specifier (identical output)
std::cout << fmt::format("{:B}\n", v); // 101010
// Alternate form adds "0b" prefix
std::cout << fmt::format("{:#b}\n", v); // 0b101010
// Width and fill (right-aligned, space-padded)
std::cout << fmt::format("{:8b}\n", v); // 101010
// Zero-fill with width
std::cout << fmt::format("{:0>8b}\n", v); // 00101010
// Left-aligned with width
std::cout << fmt::format("{:<8b}\n", v); // 101010
// Unsigned integer formatting
unsigned int u = 255;
std::cout << fmt::format("{:#b}\n", u); // 0b11111111
}
Key observations from these examples:
{:b}produces the minimal binary representation without padding{:#b}adds the0bprefix via the alternate form flag- Width specifiers combine seamlessly with binary output, using the same syntax as decimal or hexadecimal formatting
- Both signed and unsigned integers are supported
Internal Implementation
The binary formatting pipeline follows the standard {fmt} architecture:
include/fmt/base.h (lines 1548–1566)
Defines presentation_type::bin as the internal enum value for binary formatting. The library maps both 'b' and 'B' input characters to this single presentation type.
include/fmt/format.h (parse stage)
The format specifier parser recognizes the binary case and populates the format specification with presentation_type::bin. This occurs during compile-time parsing for FMT_COMPILE strings or runtime for dynamic format strings.
include/fmt/chrono.h (line 683)
Shows binary handling extending to chrono types, where duration values can also be formatted with binary specifiers.
The actual binary conversion uses optimized bit-extraction routines that operate directly on the argument's underlying value, avoiding temporary string allocations or external dependencies.
Advanced Binary Formatting Patterns
Combined Specifiers
Multiple formatting options can be combined in a single format string:
#include <fmt/format.h>
#include <iostream>
int main() {
int value = 13; // 1101 in binary
// Center-aligned with fill, plus sign, and alternate form
std::cout << fmt::format("{:*^+12#b}\n", value);
// Output: **+0b1101***
// Explanation of components:
// * - fill character
// ^ - center alignment
// + - always show sign
// 12 - minimum width
// # - alternate form (0b prefix)
// b - binary presentation type
}
Batch Formatting
Binary formatting integrates with {fmt}'s argument handling for multiple values:
#include <fmt/format.h>
#include <bitset>
#include <iostream>
int main() {
// Format multiple integers with binary
std::cout << fmt::format("flags: {:08b} {:08b} {:08b}\n", 5, 170, 255);
// Output: flags: 00000101 10101010 11111111
// Mixed format bases in single call
std::cout << fmt::format("dec={:d} hex={:#x} bin={:#b}\n", 42, 42, 42);
// Output: dec=42 hex=0x2a bin=0b101010
}
Performance Characteristics
Binary formatting in {fmt} shares the performance profile of other built-in presentation types:
- Compile-time validation — format strings are checked at compile time when using
FMT_STRINGorfmt::format_string - Type safety — only integral types accept binary specifiers; floating-point or string arguments trigger compile errors
- No heap allocation — small binary outputs use the library's internal buffer; larger outputs use optimized memory management
- Vectorized conversion — the binary digit extraction uses bitwise operations rather than division loops
Comparison with Standard Alternatives
| Approach | Syntax | Prefix Control | Performance |
|---|---|---|---|
| {fmt} binary | fmt::format("{:#b}", 42) |
Built-in (# flag) |
Optimized, type-safe |
std::bitset |
std::bitset<8>(42).to_string() |
Manual concatenation | Fixed width, runtime size |
| Manual conversion | Custom loop | Full control | Error-prone, verbose |
std::to_chars |
std::to_chars(buf, end, 2) |
None | C++17, binary base not standard |
Summary
- {fmt} implements binary formatting natively via the
bandBspecifiers, mapped internally topresentation_type::bin - The feature is located in
include/fmt/base.handinclude/fmt/format.h, with full support for width, alignment, fill, and alternate form - Use
{:#b}to include the0bprefix, and combine with standard numeric formatting options - Binary formatting achieves the same performance and type safety as decimal or hexadecimal output
- Chrono durations also support binary specifiers as shown in
include/fmt/chrono.h
Frequently Asked Questions
Does fmtlib support uppercase binary output with 0B prefix?
Capital B in the format specifier changes only the presentation type character识别;both b and B produce identical digit output (0s and 1s). The alternate form # always produces lowercase 0b regardless of specifier case. For 0B prefix, manual string manipulation is required: fmt::format("0B{:B}", value).
Can I format floating-point numbers in binary with fmtlib?
No, binary specifiers are restricted to integral types. Attempting fmt::format("{:b}", 3.14) produces a compile-time error. The library's type system enforces this constraint through detail::is_integral<T> checks in the formatting pipeline.
How do I right-align binary output with zero-padding?
Use the 0 fill character combined with right alignment: fmt::format("{:0>16b}", value) produces zero-padded 16-bit output. Alternatively, the simpler {:016b} syntax achieves the same result when left alignment is not required.
Is binary formatting available in C++20 std::format?
Yes, C++20 std::format adopted {fmt}'s binary specifiers. The b, B, and #b patterns work identically in standard library implementations that support C++20 format. However, {fmt} typically provides broader compiler support and additional performance optimizations not yet present in all standard library implementations.
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 →