必须将char显式转为unsigned char再转int,配合std::hex、std::setw(2)和std::setfill('0'),否则会因符号扩展输出异常(如\xff变成ffffffff)且不补零。

用 std::hex 和 std::setw 输出单个字节的十六进制
直接对 char 或 unsigned char 使用 std::hex 会输出其 ASCII 值(比如 'A' 变成 41),但若不加控制,std::hex 默认不补零、不固定宽度,且对负值会触发符号扩展(char 是有符号时,-1 可能输出 ffffffff)。必须显式转为 unsigned int 并配合 std::setw(2) 和 std::setfill('0')。
常见错误:std::cout —— 这里 <code>(int)c 若 c 是负 char,会先提升为负 int,再转十六进制,结果远超两位(如 0xfffffffe)。
- 正确做法:强制转为
unsigned char再转unsigned int,例如static_cast<unsigned int>(static_cast<unsigned char>(c))</unsigned></unsigned> - 每次输出前需重置宽度:
std::setw(2)只对下一个输出项生效 - 记得恢复十进制和填充字符,否则影响后续输出
遍历字符串并逐字节格式化:避免符号问题的惯用写法
对 std::string 的每个字符做十六进制输出,最稳妥的方式是用基于范围的 for 循环,配合 unsigned char 视角访问:
std::string s = "Hello";
for (unsigned char c : s) {
std::cout (c);
}
// 输出:48656c6c6f
这里关键点不是 static_cast<int>(c)</int>,而是循环变量类型必须是 unsigned char —— 否则若平台默认 char 有符号,且字符串含高位字节(如 UTF-8 中的多字节字符首字节 > 0x7f),就会出错。
- 不能写
for (char c : s),哪怕你后面static_cast也晚了 -
std::setfill('0')只需设一次(它持续生效),但std::setw(2)必须每轮都调 - 如果要空格分隔,建议在循环内加
std::cout ,而非依赖 <code>std::setfill
用 sprintf 或 std::snprintf 批量格式化到缓冲区
当需要把整个十六进制字符串存入另一个 std::string(比如用于日志或网络协议拼包),用流操作效率低、状态难管理。此时推荐 std::snprintf 配合预分配缓冲区。
一个字节对应两个十六进制字符,所以目标缓冲区长度至少为 s.size() * 2 + 1(+1 给结尾 \0)。
- 不要用
sprintf—— 它不检查缓冲区大小,易溢出 -
std::snprintf(buf, sizeof(buf), "%02x", (unsigned char)c)中的%02x自动补零、固定两位 - 注意:
%02x接收的是int,所以仍要确保传入的是非负值(即(unsigned char)c) - 若字符串含 null 字节(
\0),std::string构造时会截断,需用std::string(buf, len)显式指定长度
处理宽字符串或 UTF-8 字节流时的陷阱
std::string 存的是字节,不是“字符”。如果你拿一个 UTF-8 编码的中文字符串(如 "你好")直接按字节转十六进制,得到的是合法的 UTF-8 字节序列(如 e4bda0e5a5bd),这本身没错;但若误以为这是“字符的 Unicode 码点”,就会混淆。
真正要输出 Unicode 码点十六进制,得先解码 UTF-8(例如用 std::mbrtoc16 或第三方库),再对每个 char16_t 用 %04x 格式化。但这和“字符串十六进制格式化”是两回事。
- 绝大多数场景下,“字符串十六进制输出”指的就是原始字节流的 hex dump,UTF-8 字符串照常逐字节处理即可
- 若输入是
std::wstring,别直接遍历 —— 它的sizeof(wchar_t)因平台而异(Windows 是 2,Linux 通常是 4),直接转 hex 会丢失语义 - 跨平台代码中,避免依赖
wchar_t的位宽;如需统一处理,先转为 UTF-8std::string再格式化
实际写的时候,最容易被忽略的是 char 的符号性 —— 它不是语言标准规定的,而是由编译器和平台决定。哪怕测试时全用小写字母没出错,一旦遇到 \xff 或其他高位字节,立刻崩。所以类型转换那一步,少不得。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











