std::hex 和 std::showbase 使后续整数输出为带0x前缀的十六进制,且持续生效直至被覆盖;常见错误是误以为仅作用于下一行。

用 std::hex 和 std::showbase 控制输出格式最直接
想让 std::cout 输出十六进制,核心就两个流操纵器:std::hex 切换进制,std::showbase 加前缀。它们不改变变量本身,只影响后续输出行为,而且会持续生效,直到被覆盖或重置。
常见错误是以为加一次就只对下一行有效——其实它会“粘住”,后面所有整数输出都会走十六进制,除非手动切回去:
int x = 255; std::cout << std::hex << x << "\n"; // 输出 ff std::cout << 16 << "\n"; // 输出 10(不是 16!) std::cout << std::dec << 16 << "\n"; // 输出 16,恢复十进制
-
std::hex只影响整型输出,浮点数不受影响 - 默认不带
0x前缀,要加就得配std::showbase - 大小写由
std::uppercase控制:std::cout 输出 <code>FF
需要固定宽度或补零?用 std::setw 和 std::setfill
比如输出 4 位十六进制(不足补 0),不能只靠 std::hex,得组合宽度控制。注意:std::setw 是一次性生效的,每次输出都要重新设。
int x = 15;
std::cout << std::hex << std::setw(4) << std::setfill('0') << x << "\n"; // 输出 000f
-
std::setw(n)只对紧接的下一个输出项起作用 -
std::setfill(c)会持续生效,直到被再次调用 - 如果忘了
std::setfill('0'),默认填充空格,看起来像右对齐而不是补零 - 和
std::showbase一起用时,前缀也计入宽度,std::setw(6)配0x前缀实际留给数字的只有 4 位
转换成字符串而非直接输出?用 std::stringstream 更可控
直接输出适合调试,但做字符串拼接、日志、协议字段时,必须转成 std::string。这时候别用 printf 风格,std::stringstream 是 C++ 原生且类型安全的选择。
立即学习“C++免费学习笔记(深入)”;
int x = 27;
std::stringstream ss;
ss << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << x;
std::string hex_str = ss.str(); // "1B"
- 避免用
std::to_string:它只支持十进制,不接受进制参数 - 不要在同一个
std::stringstream里混用std::hex和std::dec后又反复读写,容易状态混乱;建议每转换一次新建一个流 - 如果只要小写、无前缀、无补零,一句
ss 就够了
处理负数时要注意符号和补码表现
用 std::hex 输出负整数,默认按有符号整型解释,显示带符号的十六进制值(如 -1 输出 ffffffff 在 32 位 int 上),这不是 bug,而是按内存补码原样输出。
- 如果想看无符号等价形式,显式转成对应无符号类型:
static_cast<unsigned int>(-1)</unsigned> - 直接输出
char类型可能被当 ASCII 字符打印,务必先转成int或unsigned int - 对于
uint8_t等窄类型,流操作默认按int提升输出,所以uint8_t(255)会输出ff,但int8_t(-1)可能输出ffffffff(取决于平台和提升规则)
十六进制转换本身没难度,难的是状态管理——流格式标志一旦设错,影响范围比预期大得多,尤其是多线程环境里共用 std::cout 时更得小心。











