使用std::hex、std::setw(2)、std::setfill('0')和static_cast(unsigned char)可正确输出固定宽度、补零、大写的十六进制字节;需避免std::dec干扰、char符号扩展及C字符串截断,推荐用std::vector存储二进制数据。

用 std::hex 和 std::setw 输出固定宽度十六进制数
直接用 std::hex 会让数字输出不带前缀、不补零、宽度不一致,根本没法当数据查看器看——比如 0xa 和 0xff 对齐困难,更别说多字节数据了。
必须组合使用:std::hex 控制进制,std::setw 固定字段宽度,std::setfill('0') 补零,std::uppercase 可选大写(如 A 而非 a)。
-
std::setw是**一次性**的,只影响下一次输出,得每字节都调一次 - 对
unsigned char输出要先转成int,否则会当字符打印(比如0x00变成空字符,终端看不见) - 别用
std::dec混在中间重置——它会把后续所有整数变回十进制,容易漏切回hex
示例:
std::cout (static_cast<unsigned char>(data[i])) <h3>按地址偏移分组显示(类似 hexdump 的行格式)</h3> <p>纯一长串十六进制没意义,数据查看器必须有地址列 + 每行固定字节数(常见 16 字节/行)+ ASCII 预览列。</p> <p>关键点不在进制转换,而在布局控制:</p> <ul> <li>地址用 <code>std::internal</code> + <code>std::setw(8)</code> 左对齐地址字段(如 <code>00000000:</code>)</li> <li>每行 16 字节就循环 16 次,不足补 <code>??</code> 或空格,避免错位</li> <li>ASCII 列要过滤不可见字符:用 <code>isprint(c) && c >= 0x20 && c 判定,否则乱码或终端异常</code> </li> <li>别忘了每行末尾换行,且 <code>std::setw</code> 不会自动刷新缓冲区,必要时加 <code>std::flush</code> </li> </ul> <h3>处理<a style="color:#f60; text-decoration:underline;" title="二进制数" href="https://m.php.cn/zt/17637.html" target="_blank">二进制数</a>据中的 null 字节和非 ASCII 字符</h3> <p>读文件或网络包时,<code>std::string</code> 容易被 <code><p>读文件或网络包时,<code>std::string</code> 容易被 <code>\0</code> 截断;用 <code>std::vector<uint8_t></uint8_t></code> 或 <code>std::span<const uint8_t></const></code>(C++20)更安全。</p></code> 截断;用 <code>std::vector<uint8_t></uint8_t></code> 或 <code>std::span<const uint8_t></const></code>(C++20)更安全。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p>输出时尤其注意:</p> <ul> <li> <code>char</code> 类型有符号性依赖平台:x86 默认 signed,<code>0xFF</code> 会被解释为 <code>-1</code>,再转 <code>int</code> 得到 <code>-1</code>,输出成 <code>ffffffff</code>(32 位补码)——必须先强转 <code>unsigned char</code> 再转 <code>int</code> </li> <li>如果原始数据是 <code>const char*</code>,别直接丢给 <code>std::cout ,那是 C 字符串语义,遇到 \0 就停</code> </li> <li>想支持宽字符或 UTF-8 预览?先做字节级 dump,ASCII 列只负责可打印 ASCII,别试图 decode</li> </ul> <h3>性能敏感场景下避免流操作符开销</h3> <p>调试时小数据无所谓,但 dump 几 MB 内存时,<code>std::cout 可能慢 5–10 倍于 <code>printf</code> 或 <code>write()</code> 系统调用。</code></p> <p>真要提速,可以:</p> <ul> <li>用 <code>std::sprintf</code> 或 <code>std::to_chars</code>(C++17)预生成十六进制字符串,再批量输出</li> <li>禁用同步:在程序开头加 <code>std::ios::sync_with_stdio(false)</code>,但之后不能混用 C stdio(如 <code>printf</code>)</li> <li>缓冲输出:把整行拼成 <code>std::string</code> 再一次 <code>std::cout ,比 48 次小输出快得多</code> </li> <li>若只是日志用途,考虑直接写入文件描述符(<code>write(STDOUT_FILENO, buf, len)</code>),绕过 stream 缓冲逻辑</li> </ul> <p>地址对齐、null 字节处理、符号扩展——这三个地方出错,dump 出来的结果看起来“像”,但数值全错,而且很难一眼发现。</p></unsigned>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










