Wiki
std::format / std::print
Existing English translations were reused. 6 current source blocks remain in Simplified Chinese, without triggering paid translation.
1.What problem does this section solve?
C++ Outputting formatted strings in C has always been rather troublesome:
printf:Fast but type-unsafe; formatting string errors can cause crashes.std::cout:Type-safe but verbose to write, and formatting control is inconvenient.std::stringstream:Feature-complete but very verbose.
C++20/23 introduced std::format (formatted strings) and std::print (direct output), combining Python-style conciseness with C++'s type safety + high performance.
2.What is this feature?
std::format(C++20): Similar to Python'sf"{name}: {score}", returns the formattedstd::string.std::print(C++23): Similar to Python'sprint(), directly outputs the formatted result to stdout.
Built on the {fmt} library, it delivers extremely high performance—approaching or even exceeding that of printf.
3.C++ Standard Edition
std::format:C++20std::print:C++23
4.编译器和系统环境
下面的代码在 Linux 和 Windows 中使用同一份写法。先按 现代C++ 的编译约定 检查标准版本和工具链支持。
只有 std::format 的例程使用 C++20;出现 <print> 的例程需要 C++23 和支持它的标准库。入门模板默认 C++20,所以复制 std::println 例程后,还要把对应 target 的编译特性提升为 cxx_std_23。Windows 终端显示中文时,源文件与终端也应使用一致的 UTF-8 设置。
5.Required header files
#include <format> // for std::format (C++20)
#include <print> // for std::print, std::println (C++23)
6.Basic syntax
// std::format:返回 string
std::string s = std::format("Hello, {}!", name);
std::string s2 = std::format("{0} + {1} = {2}", a, b, a + b);
// std::print:直接输出(不自动换行)
std::print("x = {}, y = {}", x, y);
// std::println:输出并换行
std::println("Hello, {}!", name);
// 指定输出目标:stdout / stderr 是 FILE*
std::println(stdout, "normal message");
std::println(stderr, "error message");
// 格式控制
std::format("{:.2f}", 3.14159); // "3.14" —— 保留 2 位小数
std::format("{:>10}", 42); // " 42" —— 右对齐,宽度 10
std::format("{:<10}", 42); // "42 " —— 左对齐
std::format("{:^10}", 42); // " 42 " —— 居中
std::format("{:#x}", 255); // "0xff" —— 十六进制带前缀
std::format("{:04d}", 7); // "0007" —— 前导零填充
7.Output Mode Comparison
| Method | Performance | Type safety | Conciseness | Version introduced |
|---|---|---|---|---|
printf |
Fast | ❌ | ✅ | C |
std::cout |
Slow | ✅ | ❌ | C++98 |
std::format |
Very fast | ✅ | ✅ | C++20 |
std::print |
Very fast | ✅ | ✅ | C++23 |
8.Where does std::print output to?
C++ In the standard library, there are std::print / std::println commonly used in two types of notation:
| Usage | Output target |
|---|---|
std::println("x = {}", x) |
By default, output goes to standard output, i.e. stdout |
std::println(stdout, "x = {}", x) |
Explicitly output to stdout |
std::println(stderr, "error = {}", code) |
Output to standard error stderr |
Here, stdout and stderr are in the C standard library's FILE*, and you need to include <cstdio>.
Note: the standard C++23 'sstd::println first parameter is not std::cout.std::cout is C++ 's std::ostream object, which belongs to <iostream>. You may have seen a similar {fmt} syntax in the fmt::print(std::cout, "...") library or certain extensions, but that is not the same interface as the standard library std::println.
9.Example code
9.1.Example 1: Basic usage of std::format
#include <iostream>
#include <format>
#include <string>
int main()
{
std::string name = "Alice";
int age = 25;
double score = 92.5;
// 基本占位符
std::string s1 = std::format("Name: {}, Age: {}, Score: {}", name, age, score);
std::cout << s1 << "\n";
// 指定顺序
std::string s2 = std::format("{1} is {0} years old", age, name);
std::cout << s2 << "\n";
// 保留 2 位小数
std::string s3 = std::format("Score: {:.2f}", score);
std::cout << s3 << "\n";
return 0;
}
Running result:
Name: Alice, Age: 25, Score: 92.5
Alice is 25 years old
Score: 92.50
9.2.Example 2: Based on Example 1, format control and alignment
#include <iostream>
#include <format>
int main()
{
// 右对齐,宽度 10
std::cout << std::format("[{:>10}]\n", 42);
// 左对齐,宽度 10
std::cout << std::format("[{:<10}]\n", 42);
// 居中,宽度 10
std::cout << std::format("[{:^10}]\n", 42);
// 前导零
std::cout << std::format("{:05d}\n", 7);
// 十六进制
std::cout << std::format("hex = {:#x}, oct = {:#o}\n", 255, 255);
// 打印一个简单的表格
std::cout << std::format("{:<10} {:>5} {:>7}\n", "Name", "Age", "Score");
std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Alice", 25, 92.5);
std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Bob", 22, 88.0);
std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Charlie", 24, 78.5);
return 0;
}
Running result:
[ 42]
[42 ]
[ 42 ]
00007
hex = 0xff, oct = 0377
Name Age Score
Alice 25 92.5
Bob 22 88.0
Charlie 24 78.5
9.3.Example 3: std::print direct output (C++23)
#include <cstdio>
#include <print>
#include <string>
int main()
{
std::string name = "World";
int value = 42;
// 直接输出,不换行
std::print("Hello, ");
std::print("{}", name);
std::print("!\n");
// 输出到 stdout 并换行
std::println("The answer is {}", value);
// 第一个参数也可以显式写 stdout
std::println(stdout, "stdout: {}", name);
// 带格式输出
std::println("pi = {:.3f}", 3.1415926);
// 输出到 stderr
std::println(stderr, "Error: something went wrong!");
return 0;
}
Running result:
Hello, World!
The answer is 42
stdout: World
pi = 3.142
Error: something went wrong!
10.Operation result
See the "run results" for each example above.
11.Key syntax explanation in the example
| 示例 | 讲了什么 | 新出现的语法 | 为什么这样写 | 注意事项 |
|---|---|---|---|---|
| 示例 1 | format 基本用法 | std::format("...", arg1, arg2)、{} 占位符 |
Python 风格 + C++ 类型安全 | 参数个数要和 {} 个数匹配 |
| 示例 2 | 格式控制和表格 | {:>10}、{:.2f}、{:#x} |
内置格式说明符比 printf 更丰富 | 格式控制符在 {} 内,: 后面 |
| 示例 3 | print/println 直接输出 | std::println()、std::print()、stdout、stderr |
不需要 std::cout,直接格式化输出 |
标准接口接收的是 FILE*,不是 std::cout |
12.Common Errors
错误 1:格式说明符 : 前忘了写索引
std::format("{.2f}", 3.14); // ❌ 缺少 : 前的占位符
Correct approach:std::format("{:.2f}", 3.14); or std::format("{}", 3.14);
Error 2: Parameter count mismatch
std::format("{}, {}", 1); // ❌ 有 2 个占位符,只有 1 个参数
Compilation error (this is where format is safer than printf).
错误 3:用 format 输出的字符串中包含 { 或 }
std::format("Set = {1, 2, 3}"); // ❌ {1, 2, 3} 会被误解为格式说明
Correct approach: use {{ to denote the literal { , and }} to denote the literal }:
std::format("Set = {{1, 2, 3}}"); // 输出:Set = {1, 2, 3}
13.Usage Recommendations
- C++20 uses
std::formatto replacestringstreamandsprintf: concise code, type safety, and high performance. - C++23 uses
std::print/std::printlnto simplify formatted output: by default it outputs tostdout, and you can also passstderr. - The format specifiers are very similar to Python: if you are familiar with Python's formatting syntax, you'll get up to speed quickly.
- If your compiler does not yet support C++20/23, you can use the
{fmt}library (https://github.com/fmtlib/fmt),它是标准化的基础。
14.Summary
std::format("{} + {} = {}", a, b, c)Return the formatted string.std::print("...")/std::println("...")Directly output tostdout.std::println(stderr, "...")Can output to standard error.- Type safety + powerful formatting + high performance: combines the speed of printf with the safety of cout.
- Format control:
{:.2f}decimal places,{:>10}alignment,{:#x}base,{:04d}zero padding.