0

0

C++中的std::bitset如何处理位运算?(方便地进行二进制位管理)

冰火之心

冰火之心

发布时间:2026-01-11 15:42:08

|

470人浏览过

|

来源于php中文网

原创

std::bitset的位运算符已重载,要求操作数长度一致;整数转换需注意低位截断;不可与原生整数直接混合运算;适用于编译期定长场景。

c++中的std::bitset如何处理位运算?(方便地进行二进制位管理)

std::bitset 的位运算符直接可用,无需手动实现

std::bitset 是值语义类型,operator&operator|operator^operator~ 全部重载完成,结果仍是 std::bitset。它不依赖 或循环,所有操作在编译期确定大小、运行时单指令(或极小指令序列)完成。

常见误用是试图对不同长度的 bitset 做运算:std::bitsetstd::bitset 无法直接运算,编译报错 —— 类型不匹配,不是隐式截断或扩展。

  • 运算双方必须模板参数完全一致,比如 std::bitset a, b; 才能写 a & b
  • 赋值运算符(&=, |=, ^=)同样要求左右操作数类型相同
  • ~a 是逐位取反,结果长度与 a 相同,高位补 1 是自然行为(例如 std::bitset("0010") 取反得 "1101"

如何安全地把整数转成 bitset 并参与运算

std::bitset 构造函数接受 unsigned long long,但注意:只取低 N 位(N 是模板参数),高位被静默丢弃。这不是 bug,是设计使然 —— 它不负责范围检查。

比如 std::bitset b{17}; 得到的是 "0001"(因为 17 的二进制是 10001,只保留低 4 位 0001)。若你本意是“用 4 位表示 17”,这已经越界,需提前校验。

立即学习C++免费学习笔记(深入)”;

  • 转换前建议用 if (x >= (1ULL 判断是否溢出(N 是 bitset 长度)
  • 从字符串构造更可控:std::bitset{"10101010"},但字符串内容必须全为 '0''1',否则抛 std::invalid_argument
  • 不要用 static_cast<:bitset>>(x) —— 没有这种转换,编译失败

bitset 与原生整数混合运算时的陷阱

不能直接写 my_bitset & 0xFF。因为 0xFFint,而 std::bitset 没有针对整数类型的 operator& 重载。编译器不会自动构造临时 bitset,而是报错:“no match for ‘operator&’”。

正确做法是显式构造一个同长度的 bitset:

std::bitset<8> flags{0b10100011};
auto masked = flags & std::bitset<8>{0xFF}; // ✅

如果硬要和变量混合,推荐封装一层:

template
constexpr std::bitset as_bitset(unsigned long long x) {
    return std::bitset{x};
}
// 用法:flags & as_bitset<8>(0x3F);
  • 别依赖 to_ulong() 再运算 —— 这会丢失高位(超出 unsigned long 范围时抛异常),且多一次拷贝
  • 对齐长度是关键:std::bitset & uint32_t 必须先转成 std::bitset,不能靠隐式转换

性能和适用边界:别把它当动态位容器用

std::bitset 所有长度必须在编译期确定,底层通常用一个或多个 unsigned long 存储。这意味着它极快(常数时间位运算、count() 可用内置 popcnt 指令),但也意味着无法 resize、不能 move-only、不支持迭代器遍历(只有 operator[] 随机访问)。

如果你需要运行时决定位数、频繁增删位、或需要 STL 容器接口(如 push_back),std::bitset 不合适 —— 改用 std::vector(注意其空间特化)或第三方库如 boost::dynamic_bitset

真正适合它的场景很明确:协议字段解析、状态标志集、编译期已知尺寸的掩码计算 —— 比如管理 32 个硬件寄存器位、TLS 握手标志位、或哈希布隆过滤器的固定大小位数组。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

731

2023.08.22

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

196

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

78

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.6万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号