# Rust formatting reference

> A practical map of Rust format strings, formatting traits, width, alignment, precision, number bases, output macros, and the pages that explain each rule.

HTML: https://rustprint.com/reference/rust-formatting/

Rust formatting has one small language inside another. Most confusion comes from mixing three separate questions:

1. **Which value is being formatted?**
2. **Which formatting trait should represent it?**
3. **Where should the resulting text go?**

This page is the map. The linked pages carry the checked examples and edge cases.

## The replacement field in one table

| Pattern       | Meaning                         | Read next                                                   |
| ------------- | ------------------------------- | ----------------------------------------------------------- |
| `{}`          | use `Display`                   | [Debug vs Display](/debug/debug-vs-display/index.md)                |
| `{:?}`        | use `Debug`                     | [inspect values with Debug](/debug/inspect-values/index.md)         |
| `{:#?}`       | pretty `Debug`                  | [pretty Debug](/debug/pretty-debug/index.md)                        |
| `{:>8}`       | minimum width 8, right aligned  | [width, alignment, and fill](/format/width-alignment-fill/index.md) |
| `{:.2}`       | precision 2                     | [precision](/format/precision/index.md)                             |
| `{:#x}`       | lower hex with alternate prefix | [alternate formatting](/format/alternate-format/index.md)           |
| `{:08}`       | numeric zero padding            | [signs and zero padding](/format/signs-and-zero-padding/index.md)   |
| `{{` and `}}` | literal braces                  | [escaping braces](/format/escaping-braces/index.md)                 |

The full grammar is:

```text
{ [argument] [ : format_spec ] }
```

and the format specification combines fill, alignment, sign, alternate form, zero padding, width, precision, and a formatting type. See the [format specifier grammar](/reference/format-specifier-grammar/index.md) when you need the exact order.

## Start with the trait, not the punctuation

An empty formatting type uses `Display`. A question mark uses `Debug`. Numeric format types select traits such as hexadecimal, binary, octal, exponential notation, or pointer formatting.

That matters because formatting is trait-driven. If a value does not implement the requested trait, changing width or precision cannot fix the problem.

Use:

- `Display` for intentional user-facing text
- `Debug` for programmer-facing inspection
- numeric formatting traits when the representation itself is numeric

The [formatting traits reference](/reference/formatting-traits/index.md) maps the syntax to the underlying traits.

## Width is a minimum

Width does not truncate a long value. It asks the formatter to occupy at least that many columns and to fill extra space when the output is shorter.

Alignment controls where the value sits inside that width:

- `<` left
- `^` center
- `>` right

A fill character can appear immediately before the alignment operator. This is why `{:.^8}` means "center within width 8 and fill with dots."

For strings and table-like output, start with [width, alignment, and fill](/format/width-alignment-fill/index.md).

## Precision is type-dependent

Precision is not one universal "number of characters" switch.

For floating-point output it controls digits after the decimal point in the common fixed-point case. For strings it can limit the displayed content. Other formatting traits interpret it according to their own rules.

Use the dedicated [precision guide](/format/precision/index.md) instead of assuming that `{:.2}` means the same thing for every type.

## Numeric flags interact

Numeric formatting has combinations that look simple until signs and prefixes appear.

The alternate flag `#` can request prefixes such as `0x` for hexadecimal. Zero padding is sign-aware and prefix-aware. A pattern such as `{:#08x}` is therefore not equivalent to manually filling a string with zeroes.

Use [alternate formatting](/format/alternate-format/index.md) together with [signs and zero padding](/format/signs-and-zero-padding/index.md) for numeric output.

## Arguments can be positional, named, or captured

Modern Rust format strings can capture variables from the surrounding scope. Width and precision can also come from arguments.

That gives you patterns such as:

```text
{value:>width$}
```

The format string itself still has to be a literal so the compiler can parse and validate it. If the format must be assembled dynamically at runtime, the normal formatting macros are not a runtime template engine.

See [arguments and capture](/format/arguments-and-capture/index.md) and [runtime format strings](/format/runtime-format-strings/index.md) for the boundary.

## Formatting and destination are different decisions

The formatting language describes the representation. The macro decides where the formatted output goes.

| Goal                          | Typical macro           |
| ----------------------------- | ----------------------- |
| stdout with newline           | `println!`              |
| stdout without newline        | `print!`                |
| stderr                        | `eprint!` / `eprintln!` |
| new `String`                  | `format!`               |
| existing writer or buffer     | `write!` / `writeln!`   |
| prebuilt formatting arguments | `format_args!`          |

The [output macro map](/output/output-macros/index.md) explains these destinations, and the [Output Macro Chooser](/tools/output-macro-chooser/) can select one from the intended destination and newline behavior.

## Debug output is not serialization

`Debug` exists for programmer-facing inspection. Its representation is not a wire format, persistence format, or compatibility contract.

If another program has to parse the output later, use a real serialization format with an explicit schema or compatibility policy.

The same warning applies to pretty Debug. It is for humans reading diagnostics, not for storing durable data.

## The fast path

If you have a concrete formatting string and want to decode it, open the [Rust Format Explorer](/tools/format-string/).

If you only need syntax at a glance, use the [formatting cheat sheet](/reference/formatting-cheat-sheet/).

If the compiler rejects the expression, start in [formatting errors](/errors/doesnt-implement-display/index.md) or paste the diagnostic into the [Formatting Error Explainer](/tools/error-explainer/).

## Sources

- [std::fmt](https://doc.rust-lang.org/stable/std/fmt/)

## Related RustPrint guides

- [Rust format strings - syntax, width, precision, and traits](/format/format-strings/index.md): Read Rust format strings from {} through argument capture, width, precision, alignment, escaping, and formatting traits.
- [Rust format specifier grammar](/reference/format-specifier-grammar/index.md): Read the exact order of fill, alignment, sign, alternate, zero, width, precision, and type in a Rust format specification.
- [Rust formatting traits - Display, Debug, hex, binary, and more](/reference/formatting-traits/index.md): Map Rust format syntax such as {}, {:?}, {:x}, {:b}, and {:e} to the std::fmt traits Display, Debug, LowerHex, Binary, and LowerExp.
- [Rust output macros: print!, eprintln!, write!, and format!](/output/output-macros/index.md): Choose the right Rust output macro for stdout, stderr, an owned String, or an existing writer, including newline, flushing, and buffering behavior.
