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, prepends 0b to 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 the 0b prefix 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_STRING or fmt::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 b and B specifiers, mapped internally to presentation_type::bin
  • The feature is located in include/fmt/base.h and include/fmt/format.h, with full support for width, alignment, fill, and alternate form
  • Use {:#b} to include the 0b prefix, 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →