std::bitset 是转换十进制整数到二进制字符串最省事的方法(限 int 范围内),但需编译期确定位宽、自动补前导零、不支持运行时长度,适用于输入范围已知的场景。

用 std::bitset 转十进制整数到二进制字符串最省事
只要数字在 int 范围内(通常是 ±2³¹),std::bitset 是最直接、无符号、不手写循环的方案。它本质是编译期确定位宽的固定长度容器,不是“动态字符串”,所以得提前知道最大位数。
常见错误现象:std::bitset(12) 输出 "00001100",但你想要 "1100" —— 它补前导零,且不支持运行时指定长度。
- 使用场景:已知输入范围(比如总是 0~255),需要可读性好、不易出错的转换
- 参数差异:
std::bitset<n></n>的N必须是编译期常量,不能写成std::bitset<n>(x)</n> - 性能影响:零开销,纯栈上操作;但若 N 过大(如
bitset),可能浪费空间 - 示例:
std::cout (42).to_string();→"00101010"
用 std::to_string 配合 std::stoi 不行,别试
std::to_string 只支持十进制输出,没有进制参数。有人试图先转成字符串再手动解析,或者误以为 std::stoi("1010", nullptr, 2) 能反向生成二进制——其实那是把字符串当二进制解释成整数,不是转换方向。
典型错误:std::to_string(42, 2) 编译失败;std::stoi("42", nullptr, 2) 报 std::invalid_argument,因为 "42" 不是合法二进制字面量。
立即学习“C++免费学习笔记(深入)”;
- 原因:C++ 标准库没提供任意进制的
to_string重载,这是有意设计,避免接口膨胀 - 替代思路:自己写循环或用
std::stringstream+std::setbase,但仅对输出到流有效,不能直接得std::string - 兼容性注意:
std::setbase(2)在std::ostringstream中只影响整数输出,且对负数行为未定义(通常直接崩溃或输出空)
手写除二取余法要注意符号和顺序
这是最通用、可控性最强的方式,适合任意大小整数(包括 long long)、需要去掉前导零、或处理负数的情况。但容易在两处翻车:余数顺序反了,以及负数直接除会出错。
常见错误现象:输出是 "0101" 而不是 "1010";输入 -5 得到奇怪结果甚至死循环。
- 正确做法:用
unsigned类型做除法,或对负数先转正再加前缀"-" - 顺序问题:每次
% 2得到的是最低位,必须逆序拼接(用std::string::insert(0, "0")或最后std::reverse) - 边界注意:输入 0 时循环不执行,要单独处理
- 示例片段:
if (n == 0) return "0"; std::string s; unsigned u = n
用 std::format(C++20)最干净,但别忽略编译器支持
如果你用的是 GCC 13+、Clang 15+ 或 MSVC 19.32+,std::format 支持 {:b} 格式说明符,一行搞定:std::format("{:b}", 42) → "101010"。它自动去前导零、支持负数(输出 "-101010"),语义清晰。
容易踩的坑:GCC 默认不启用 std::format,需加编译选项 -std=c++20 -lstdc++fs(旧版)或确认 libstdc++ 版本;Clang 需链接 libc++ 并开启 -stdlib=libc++。
- 兼容性影响:C++20 之前完全不可用,老项目慎用
- 性能:比
bitset略慢(涉及格式化引擎),但对一般用途无感 - 注意点:
{:b}不接受宽度或填充控制(比如{:08b}是非法的),要补零得自己拼接
真正麻烦的不是“怎么转”,而是决定要不要处理负数、前导零、超大整数、以及目标 C++ 标准是否允许你用新特性。选哪个方案,先看编译器版本和输入范围,再决定要不要多写几行健壮逻辑。










