用printf打印char数组十六进制值时,必须将每个元素强制转换为unsigned char,否则负值字节会因符号扩展导致输出错误(如ffffffff);推荐格式为printf("%02x ", (unsigned char)arr[i])。

用 printf 打印字符数组的十六进制值最直接
想把 char 数组每个字节转成两位十六进制(如 0x41 或 41),printf 是最快捷的方式,尤其适合调试时快速查看内存内容。
关键点在于:必须把 char 强转为 unsigned char,否则负值字节(如 0xFF)会被解释成负数,%x 会输出补码形式的长十六进制(比如 ffffffff),完全失真。
-
printf("%02x ", (unsigned char)arr[i]);—— 输出不带0x前缀、左补零的两位小写十六进制(如ff) -
printf("0x%02x ", (unsigned char)arr[i]);—— 加前缀,更符合习惯 - 用
%02X可输出大写字母(如FF) - 别用
%x直接传char,这是最常见的错误源头
std::cout 配合 std::hex 和 std::setw 更 C++ 风格
如果项目禁用 C 风格 I/O,或你坚持用 std::cout,就得手动控制格式:默认 std::hex 不补零、不固定宽度,且对 char 会直接输出 ASCII 字符而非数值。
- 必须用
static_cast<unsigned char>(arr[i])</unsigned>转型,否则cout 可能输出乱码或空字符 - 加
std::hex开启十六进制,但需配合std::setw(2)和std::setfill('0')补零 - 每次输出前要重置
std::dec,否则后续整数也会被当十六进制打印 - 示例:
std::cout (arr[i])
遇到 00 字节就提前截断?那是当成 C 字符串用了
如果你发现输出总在某个位置停下(比如只打出前 5 个字节),大概率是误用了 strlen 或 std::string(arr) 来获取长度。C++ 字符数组不是字符串——只要没显式以 \0 结尾,就不该按字符串处理。
- 必须传入明确长度,例如
int len = 16;,然后循环i = 0; i - 若数组是栈上定义的,可用
sizeof(arr)/sizeof(arr[0]),但仅限于**非指针场景**(函数参数传进来就失效) - 千万别写
for (char c : arr)—— 若arr是指针,这会编译失败;若是数组,但含\0,范围 for 仍会遍历全部元素(不会截断),但语义已偏离“按字节输出”的本意
打印到文件或缓冲区时注意缓冲和类型安全
用 fprintf 写文件和用 sprintf/snprintf 写缓冲区,原理同 printf,但风险更高:
-
sprintf容易溢出,务必用snprintf(buf, sizeof(buf), ...)并检查返回值 - 目标缓冲区类型要是
char[],不能是std::string::data()(C++11 后非 const,但仍是未初始化内存,且长度难控) - 写二进制数据时,文件要以
"wb"模式打开,避免 Windows 下\n被自动转成\r\n - 如果最终要 hex dump 成类似
00000000: 48 65 6c 6c 6f 20 57 6f 72 6c 64 00的格式,建议直接用现成工具(如xxd)或封装一个带地址偏移和 ASCII 回显的小函数,别硬啃格式对齐
(unsigned char) 这一步漏掉,结果就不可信。尤其在处理网络包、加密密钥、图像原始数据这类含高位字节的场景,错一个字节,后续全崩。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











