std::oct 设置后不自动重置,后续整数均按八进制输出;应每次显式使用或配对 std::dec 切回十进制。示例:int x = 64; std::cout

用 std::oct 和 std::cout 输出八进制
直接输出到控制台最常用,但容易漏掉关键设置:std::oct 是流操纵符,只对后续输出生效,且**不自动重置进制**,一旦设了,后面所有整数都会按八进制打印。
实操建议:
- 每次使用前显式加上
std::oct,或配对用std::dec切回十进制 - 别依赖“默认状态”,尤其在多处输出混用时
- 示例:
int x = 64; std::cout << std::oct << x << " "; // 输出 100 std::cout << std::dec << x; // 输出 64,必须手动切回
用 std::to_chars 转成八进制字符串(C++17)
这是唯一标准库中能生成 char* 八进制表示的无内存分配方式,但注意:std::to_chars 不支持八进制,**它只支持二、十、十六进制**。想转八进制必须自己实现或换方案。
常见错误现象:std::to_chars(buf, buf + size, 42, 8) 编译失败——因为第三个参数是底数,而该函数根本不接受 8 作为合法值。
立即学习“C++免费学习笔记(深入)”;
替代做法:
- 用
std::ostringstream配合std::oct,再取.str() - 手写循环除 8 取余(适合嵌入式或极致性能场景)
- 第三方库如 fmt:
fmt::format("{:o}", 42)
用 sprintf 或 std::sprintf 转八进制字符串
简单直接,但要注意缓冲区大小和符号处理。C 风格函数仍有效,只是得自己算够不够空间。
关键点:
- 八进制最大位数 ≈
sizeof(int) * 8 / 3 + 1(+1 防负号,但 int 八进制无符号前缀) -
%o不带前导0,%#o才加(如0123),但 C++ 中std::sprintf行为与 C 一致 - 示例:
char buf[12]; std::sprintf(buf, "%o", 64); // buf = "100"
- 别传
int给%x或%o以外的格式符,否则未定义行为
负数转八进制的陷阱
C++ 没有“负八进制字面量”语法,-0123 是先解析 0123(八进制 83),再取负,结果是 -83。这不是补码八进制表示。
如果你真需要二进制补码对应的八进制字符串(比如调试寄存器),得先转成无符号类型再处理:
- 对
int x = -1,用static_cast<unsigned>(x)</unsigned>得到全 1 的位模式,再转八进制才对应底层存储 - 否则直接
std::oct 会输出 <code>-1(即字面量负号 + 十进制 1),不是你想要的 - 八进制本身不区分有/无符号,它只是数字的一种表示;语义由上下文(类型、解释方式)决定
真正麻烦的是跨平台位宽假设——int 在不同系统可能是 16/32/64 位,导致八进制字符串长度不可控。如果协议或日志要求固定宽度,得自己补零或截断。










