c++oding="utf-8" ?>
std::to_chars是C++中数字转字符串最快最可控的方案,但需足量缓冲区、检查ec、避免误用;int32_t/64_t最坏分别需11/20字节,double推荐24–32字节;必须检查result.ec,不写'\0',不保证C字符串兼容。

std::to_chars 是目前 C++ 中数字转字符串最快、最可控的方案,但快的前提是你给够缓冲区、检查 ec、不把它当 sprintf 用。
缓冲区大小算错是压测翻车第一原因
常见错误是传 buf + 16 给 int64_t:-9223372036854775808 需要 20 字节(含负号),buf + 16 直接触发 std::errc::value_too_large,但程序不崩溃——压测时大量返回失败却没被发现,误判为“性能差”。
-
int32_t最坏情况:11 字节(-2147483648) -
int64_t最坏情况:20 字节(-9223372036854775808) -
double推荐至少std::numeric_limits(通常 24–32 字节)::max_digits10 + 8 - 别依赖
sizeof(buf)—— 若用std::array,务必传buf.data(), buf.data() + buf.size()
浮点数转换必须检查 ec,且平台行为不一致
压测中浮点路径最容易暴露实现差异:GCC 11 及更早版本在 DBL_MAX 或极小值上可能退化为科学计数法,或精度丢失;而 MSVC 2019 16.10+ 和 Clang 14+ 的 libc++ 基本稳定。更隐蔽的是,std::to_chars 对浮点数要求“最短唯一表示”,但不保证和 std::to_string 输出一致——比如 0.1 可能输出 "0.1",也可能输出 "0.10000000000000001"(取决于是否满足 round-trip 精度)。
- 永远检查
result.ec == std::errc{},不能只看ptr是否移动 - 若需固定小数位(如日志中统一保留 3 位),
std::to_chars不支持,得 fallback 到std::sprintf或手写格式化逻辑 - 跨平台交付前,用边界值(
0.0、1e-10、DBL_MAX、INFINITY)实测输出长度与内容
别拿 std::to_chars 和 sprintf 比“写完就用”
std::to_chars 不写 '\0',也不保证输入缓冲区可直接当 C 字符串用。压测中有人直接把 buf 传给 strlen 或 printf("%s", buf),结果读到垃圾内存——因为 result.ptr 后面没终止符。
- 构造
std::string:用std::string{buf, result.ptr},不是std::string{buf} - 转 C 字符串:需手动补
'\0',例如*result.ptr = '\0';(前提是缓冲区有富余空间) - 性能对比必须对齐前提:
sprintf要用snprintf防溢出,且两者都禁用 locale(std::setlocale(LC_ALL, "C")) - 高频小整数场景(如计数器序列化),
std::to_chars热点函数常被编译器内联为几十条指令;sprintf却绕不开格式字符串状态机,哪怕只是"%d"
真正难的不是调用函数,而是理解它不帮你做任何事:不分配、不补 '\0'、不跳空格、不查 locale、不处理宽度填充。你给多少,它吃多少;你查什么,它返什么。漏掉任意一环,压测数据就不可信。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











