
std::stringstream 怎么转 int 到 hex 字符串(带前缀)
直接用 std::hex 和 std::showbase 最省事,但默认不补零、不转大写,且容易漏掉 std::uppercase 或 std::setw 配合 std::setfill。
- 要输出
"0xFF":必须加std::showbase,否则只有"FF" - 要固定 2 位(如
"0x0F"):得用std::setw(2)+std::setfill('0'),且setw只对下一个输出项生效 - 十六进制字母默认小写,加
std::uppercase才变大写
示例:
立即学习“C++免费学习笔记(深入)”;
int x = 15;
std::stringstream ss;
ss << std::hex << std::showbase << std::uppercase << std::setw(2) << std::setfill('0') << x;
std::string s = ss.str(); // 得到 "0x0F"
std::format(C++20)怎么安全生成 hex 字符串
std::format 更简洁、类型安全,但要注意编译器支持和格式说明符写法 —— 它不认 std::hex 这类流操纵符,得用格式字符串。
-
{:x}→ 小写无前缀("ff") -
{:#x}→ 小写带0x("0xff") -
{:#X}→ 大写带0X("0XFF") - 补零要用
{:02x}或{:#04x}:数字表示总宽度,0表示用 0 填充
示例:
立即学习“C++免费学习笔记(深入)”;
std::string s = std::format("{:#04x}", 15); // "0x0f"
std::string t = std::format("{:#04X}", 255); // "0XFF"
注意:std::format 在 GCC 13+ / Clang 15+ 默认可用,MSVC 2022 17.5+ 支持;若编译失败,先确认是否开了 -std=c++20 且标准库完整。
为什么 sprintf / snprintf 不推荐用于 C++ 字符串转换
不是不能用,而是容易踩缓冲区溢出、类型不匹配、无符号整数截断三连坑。
-
sprintf(buf, "%x", -1)→ 输出大量"ffffffff"(有符号转无符号解释),但没报错 -
snprintf要手动管理buf大小,std::string的.data()在 C++20 前还不能直接当可写缓冲区用 - 格式符和参数类型不一致(比如用
%x传long long)会触发未定义行为,编译器不一定警告
除非在嵌入式等极度受限环境,否则优先用 std::stringstream 或 std::format。
unsigned char 数组怎么转 hex 字符串(如二进制 dump 场景)
这是最常被低估的场景:逐字节转两位 hex,还要避免符号扩展导致高位全 F。
- 直接对
unsigned char用std::hex没问题,但若误写成char,负值会被提升为int(如0xFF变成-1→ 升级为0xFFFFFFFF→ 输出"ffffffff") - 推荐显式转
unsigned int:static_cast<unsigned int>(b)</unsigned>,再格式化 - 循环中别反复构造
std::stringstream,可复用一个对象并调用.str("")清空
示例(安全转 4 字节):
unsigned char data[] = {0x0a, 0xff, 0x80, 0x00};
std::stringstream ss;
for (unsigned char b : data) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(b);
}
std::string hex_str = ss.str(); // "0aff8000"
真正麻烦的是边界对齐、分组空格、大小端隐含假设——这些不在基础转换里,但一旦需求出现,就不再是“转个 hex”那么简单了。










