std::stringstream + std::hex 适合小数组和调试输出,需配合 std::setw(2) 和 std::setfill('0') 补零,否则单字节如 0xf 会输出为 f。

用 std::stringstream + std::hex 最快上手
直接拼接十六进制字符最常用,适合小数组、调试输出。注意默认不补零、不分隔、字母小写。
常见错误是漏掉 std::setw(2) 和 std::setfill('0'),导致单字节变一位(如 0xf 输出成 f)。
- 每字节必须用
std::setw(2) 补零 -
std::hex仅影响整数输出,对char需显式转成unsigned int,否则符号扩展可能出错(如0xff变成0xffffffff) - 示例:
std::stringstream ss;<br>for (unsigned char b : bytes) {<br> ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(b);<br>}<br>std::string hex = ss.str();
用 sprintf / snprintf 控制格式更稳
当需要大写 HEX(A-F)、固定宽度或嵌入空格/冒号分隔时,C 风格格式化反而更直白,且避免 iostream 开销。
容易踩的坑是缓冲区大小算错:n 字节 → 最多 2×n 字符,别忘结尾 \0;还有 char 直接传给 %02x 会因符号位截断。
立即学习“C++免费学习笔记(深入)”;
- 务必用
unsigned char*指针传入,或强制转unsigned int - 推荐用
snprintf而非sprintf,防止溢出 - 大写加
%02X,加空格则用"%02X "(注意末尾空格需手动裁剪)
用 C++20 std::format 最简洁(但注意编译器支持)
如果项目已用 GCC 13+/Clang 15+/MSVC 19.32+,std::format 是目前最干净的写法,天然支持 {:02x} 格式。
问题在于旧标准下不可用,且某些 STL 实现(尤其 libstdc++ 早期版本)对 std::format 的 char 处理仍有 bug,建议先测 std::format("{:02x}", (unsigned char)0xff) 是否输出 ff。
- 格式字符串用
{:02x}(小写)或{:02X}(大写) - 每个字节单独 format 再拼接,或用 range-based loop +
std::accumulate - 避免直接 format 整个
std::vector<uint8_t>——std::format不支持容器批量格式化
性能敏感场景别用 iostream,改用查表法
高频转换(比如网络包日志、加密模块)中,std::stringstream 构造/析构开销明显。查表法(256 元素静态数组)可做到 O(n) 无分支。
核心是预生成 256 个两位 hex 字符串(如 "00" 到 "ff"),然后按字节索引拼接。比 sprintf 快约 2–3 倍,内存只多 512 字节。
- 查表数组声明为
static constexpr const char* hex_lut[256]或static constexpr std::array<std::string_view, 256> - 拼接时用
reserve(2 * len)避免多次 realloc - 别忘了把
char转成unsigned char再作数组索引,否则负值越界
实际用哪一种,取决于你是否要兼容老编译器、是否在 tight loop 里调用、以及 hex 字符串后续要不要插入分隔符。查表法看着重,但跑得真快;std::format 看着轻,但得确认工具链撑得住。


















