std::stringstream最稳妥,适合大多数场景:通用、可读性好、不依赖编译器扩展,支持前缀、大小写和填充控制;负数按补码解释,需转无符号类型获无符号语义。

用 std::stringstream 最稳妥,适合大多数场景
这是 C++ 标准库中最通用、可读性最好的方式,不依赖编译器扩展,且能控制前缀、大小写和填充。
- 默认不带
0x前缀,需手动加;用std::hex开启十六进制输出,std::uppercase控制字母大小写 - 负数会按补码解释(比如
-1输出为ffffffff,在 32 位int下),若要无符号语义,务必先转成unsigned int或对应无符号类型 - 填充要用
std::setfill和std::setw,且必须在插入数值前设置,否则无效
int x = 255;
std::stringstream ss;
ss << std::hex << std::setw(4) << std::setfill('0') << (unsigned int)x;
std::string s = ss.str(); // "00ff"
用 std::format(C++20)最简洁,但注意编译器支持
如果你的项目已启用 C++20 且使用较新编译器(GCC 13+、Clang 15+、MSVC 19.32+),std::format 是最干净的选择。
- 格式说明符
"{:x}"输出小写,"{:X}"输出大写,"{:#x}"自动加0x前缀 - 不支持直接指定最小宽度 + 填充零的组合格式(如
"{:04x}"在 GCC 13.1 之前会报错),得拆成"{:04x}"(GCC 13.1+ / Clang 15+ 支持)或改用"{:x}"+ 手动std::format("{:0>4}", s) - 对负数同样按有符号整数处理,建议显式转换:
std::format("{:x}", static_cast<unsigned int>(x))
std::string s = std::format("{:04x}", static_cast<unsigned int>(255)); // "00ff"
避免用 itoa —— 它不是标准函数
很多老代码或网上示例会用 itoa(x, buf, 16),但它既不是 C 标准也不是 C++ 标准函数,是某些平台(如 MSVC、glibc 扩展)私有的。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 在 Clang/Linux 上通常不可用,编译直接失败;即使可用,行为也不统一(比如缓冲区长度检查、空终止保证)
- 没有类型安全:参数是
int,无法区分short、long long等,容易截断或溢出 - 替代方案明确:用
std::to_chars(C++17,无内存分配、高性能)或前述流/格式化方式
std::to_chars 适合高性能场景,但需自己管理缓冲区
当你要频繁转换大量整数(比如日志、序列化),且对性能敏感时,std::to_chars 是唯一标准、零分配、无异常的选项。
立即学习“C++免费学习笔记(深入)”;
- 它只写入字符,不加前缀、不填充、不分隔,返回一个
std::to_chars_result指示写入位置,你得自己算长度、构造std::string - 缓冲区必须足够大:32 位整数最多 8 个十六进制字符,64 位最多 16 个,建议栈上分配
char buf[17]并确保以\0结尾(std::to_chars不写结尾零) - 不处理负数——传入负值会返回
std::errc::invalid_argument,所以必须先转无符号类型
int x = 255;
char buf[17];
auto [ptr, ec] = std::to_chars(buf, buf + sizeof(buf), static_cast<unsigned int>(x), 16);
if (ec == std::errc{}) {
std::string s(buf, ptr);
}
实际用哪个,取决于你手头的 C++ 标准版本、是否需要前缀/填充、以及性能要求。最容易出错的是忽略负数的二进制解释和无符号转换,这点在所有方法里都一样关键。

















