bitset转二进制字符串用to_string()得高位在前且含前导零;转回需严格0/1字符串,长度超模板上限或含非法字符会抛异常;非常规位宽应改用vector或手动位运算。

bitset转二进制字符串:用to_string()但要注意高位在前
std::bitset的to_string()返回的是从最高位到最低位的字符串,比如bitset("1010")调用to_string()得到"1010",不是反序。这点和手动循环取test(i)再拼接效果一致,但更简洁。
常见错误是误以为它会自动去掉前导零——不会。bitset(5)转成字符串是"00000101",长度固定为模板参数值。如果需要截掉左边的'0',得自己用find_first_of('1')找起始位置再substr。
- 必须指定模板大小(如
bitset),不能运行时决定 - 若原始数值位宽小于模板大小,结果含前导零,这是设计行为,不是bug
- 想兼容不同位宽?只能封装函数,根据实际值算出最小所需位数再构造新
bitset
二进制字符串转bitset:构造函数直接支持,但字符串格式要严格
bitset构造函数接受std::string或const char*,但只认'0'和'1',遇到空格、换行、'x'或超出长度立刻抛std::invalid_argument。不是静默截断,也不是忽略非法字符。
典型报错:std::logic_error: basic_string::_M_construct null not valid往往是因为传了nullptr;而std::invalid_argument多来自字符串含非01字符或长度超模板上限。
立即学习“C++免费学习笔记(深入)”;
- 字符串长度可以小于模板参数,右边自动补
'0'(即低位对齐) - 字符串长度不能大于模板参数,否则构造失败
- 推荐先用
std::all_of(s.begin(), s.end(), [](char c){ return c=='0' || c=='1'; })预检
处理非常规长度(比如27位):别硬套bitset,改用vector或手动位运算
bitset模板参数必须是编译期常量,无法适配运行时才知道长度的二进制字符串。例如解析协议里带长度字段的bit流,用bitset就得写死最大可能长度(如bitset),浪费空间且逻辑绕弯。
这时std::vector<bool></bool>虽有空间优化但接口弱(不支持to_string),更实用的是手写转换:遍历字符串,用value |= (c == '1') 累加到<code>uint64_t;或者用boost::dynamic_bitset(如果允许第三方依赖)。
-
vector<bool></bool>迭代器解引用返回代理对象,不能取地址,慎用于复杂算法 - 若位数≤64,直接转
uint64_t最轻量;超64位又不想引入boost,就分段存多个整数 - 别试图用
reinterpret_cast把字符串内存强转成bitset——类型不匹配,UB
性能敏感场景:避免临时字符串,优先用to_ullong()或to_ulong()
如果后续要算术运算或比较,to_string()生成堆分配字符串是多余开销。直接用to_ullong()(C++11起)转成整数更快,且能被编译器常量折叠。
但注意:若bitset位宽超过unsigned long long能表示的范围(通常是64位),调用to_ullong()会抛std::overflow_error。此时必须降级处理——要么确认输入范围,要么改用to_string()再配合大数库。
-
to_ulong()在32位系统上更易溢出,优先用to_ullong() - 调试时可用
cout 直接输出二进制(重载了<code>operator),比<code>to_string()少一次拷贝 - 频繁转换建议缓存结果,
bitset本身是POD,拷贝廉价,但字符串构造不是
真正麻烦的从来不是“怎么转”,而是位序约定(网络字节序 vs 主机序)、前导零语义(是填充还是有效位)、以及运行时长度不可知这三件事。选bitset前先问清楚:这个长度,真的编译期就知道吗?


















