C++进制转换优先用std::bitset处理固定位宽二进制、stringstream处理8/10/16进制字符串互转;bitset模板参数须编译期常量,调用to_string()获取字符串,自动高位补零。

直接说结论:C++ 里进制转换别硬写循环,优先用 std::bitset 处理固定位宽的二进制,用 std::stringstream + std::hex/std::oct 做整数与字符串间的任意进制互转;但要注意 stringstream 不支持直接转任意进制(比如转 3 进制),bitset 只支持 2 进制且长度必须编译期确定。
用 std::bitset 转二进制字符串最稳
适合把一个整数(≤64 位)快速转成固定长度的二进制字符串,比如调试寄存器、生成掩码。
-
bitset构造时传入整数,它会自动按补码截断填充,例如std::bitset(255)得到"11111111",std::bitset(-1)也是"11111111"(因为 -1 补码就是全 1) - 不能传入运行时变量做模板参数:
int n = 16; std::bitset是非法的 —— 模板参数必须是常量表达式(x) - 想转成字符串?调用
.to_string(),不是.c_str()(它没这个方法) - 注意高位补零:
std::bitset(5)→"0000000000000101",不需要手动 pad
用 std::stringstream 转 8/10/16 进制字符串
这是标准库最通用的整数 ↔ 字符串进制转换方式,但只内置支持八、十、十六进制。
- 转字符串:设置流格式标志,例如
int x = 255; std::stringstream ss; ss << std::hex << x; // 小写十六进制 → "ff" ss.str(); // 得到字符串 // 同理:std::oct → 八进制,std::dec → 十进制(默认)
- 从字符串读整数:同样靠标志,但要确保字符串格式匹配,否则
failbit被置位 -
ss >> std::hex >> y会跳过前导空格,但不跳过0x前缀 —— 如果字符串带"0xff",得先去掉前缀或用std::stoi(str, nullptr, 16) - 大写十六进制?加
std::uppercase:ss →"FF"
转任意进制(如 3、7、36)只能手写
bitset 和 stringstream 都不支持。必须自己实现除基取余,尤其注意负数处理。
立即学习“C++免费学习笔记(深入)”;
- 正数直接循环取余,倒序拼接;负数建议先转为无符号类型再算,避免右移符号扩展干扰
- 基数 >10 时需映射数字到字符:0–9、a–z(最多到 36 进制),别忘了大小写控制
- 常见坑:
0输入必须单独处理,否则循环不进,结果为空字符串 - 示例逻辑:
std::string to_base(int n, int base) {
if (n == 0) return "0";
bool neg = n < 0;
unsigned int un = neg ? -n : n; // 防止 INT_MIN 取负溢出,应改用 long long 或 uint64_t
std::string res;
while (un) {
int r = un % base;
res += (r < 10) ? '0' + r : 'a' + r - 10;
un /= base;
}
if (neg) res += '-';
std::reverse(res.begin(), res.end());
return res;
}性能与安全提醒
频繁转换时,stringstream 构造/析构开销比纯算法大;bitset 零拷贝但内存占用固定(如 bitset 占 128 字节)。
- 不要在 tight loop 里反复创建
stringstream对象,可复用并调用ss.str("")和ss.clear()重置 -
std::stoi/std::stol支持进制参数,比stringstream简洁,但异常处理更重(抛std::invalid_argument或std::out_of_range) - 所有字符串转整数操作,都需检查是否转换完整:用
std::strtol的endptr或stringstream::eof(),否则"123abc"会被当成123静默接受
真正麻烦的从来不是“怎么转”,而是“边界怎么控”——负数、溢出、前缀、空格、不完整输入,这些地方一漏,线上就出隐蔽 bug。









