一些简单的原子操作,往往能组合出复杂而强大的功能。位操作的深远意义不在于表示一种数值,而是可能的情况数。我虽然暂时不知道bitset能组合出如何复杂的功能,但冥冥之中却有这样的直觉感受。
basis
bitset所在的头文件
<bitset>
命名空间std
bitset<N>属于非类型模板参数
#include <bitset>
std::bitset<8> bs;
// 模板参数是一个size_t类型的数值(value),而非一个类型
// numeric_limits<size_t>::min() == 0
// std::bitset<8> 表示的二进制位为8位,
// 默认的构造函数将其初始为全0
cout << bs.to_ulong() << endl; // 0
cout << bs.to_string() << endl; // 00000000
bitset 的构造
唯一需要注意的是,bitset<>模板类虽然重载了中括号运算符,bs[0]表示的是将该数值转换为二进制时的最末尾元素,而非首位(其意义和数组并不相同)。
std::bitset<8> bs;
//bs[0] = 1; // 0000 0001
//bs[7] = 1; // 1000 0000
- 默认无参构造
初始化全部位为0
-十进制或者16进制数值
std::bitset<8> bs(7);
bs.to_string() // 0000 0111
std::bitset<8> bs(0x07);
bs.to_string() // 0000 0111
这里也存在一些高大上的构造方式:
bitset<numeric_limits<unsigned short>::digits> bs1(267);
// 16位
bitset<numeric_limits<unsigned long>::digits> bs2(267);
// 32位
- 用string对象
std::bitset<8> bs("00000111");
bs.to_ulong(); // 7
bitset的操作
成员函数 | 函数功能 |
---|---|
bs.any() | 是否存在值为1的二进制位 |
bs.none() | 是否不存在值为1的二进制位 或者说是否全部位为0 |
bs.size() | 位长,也即是非模板参数值 |
bs.count() | 值为1的个数 |
bs.test(pos) | 测试pos处的二进制位是否为1 与0做或运算 |
bs.set() | 全部位置1 |
bs.set(pos) | pos位处的二进制位置1 与1做或运算 |
bs.reset() | 全部位置0 |
bs.reset(pos) | pos位处的二进制位置0 与0做或运算 |
bs.flip() | 全部位逐位取反 |
bs.flip(pos) | pos处的二进制位取反 |
bs.to_ulong() | 将二进制转换为unsigned long输出 |
bs.to_string() | 将二进制转换为字符串输出 |
~bs | 按位取反 效果等效为bs.flip() |
os << b | 将二进制位输出到os流 小值在右,大值在左 |
一些高级用法
首先看一个简单实例:
"1000 0000" - > 1
"1000 1000" - > 17
如何实现2进制向10进制的转换,而且二进制的表示形式是一种逆序的形式,即低位在前。
int bin2dec(const string& bin)
{
std::bitset<8> bs(string(bin.rbegin(), bin.rend()));
return bs.to_ulong();
}
这里回顾开头引用中的话,bitset的强大之处不在于表示一个二进制的数值,而是表达一种情况数,一个二进制位可以表示两种情况,两个二进制位可以表示4种状况数,3个二进制位可以表达8种状况数,等等。
将Bitsets视为一组标志
enum Color{red, yellow, green, blue, white, black, numColors};
// 初始状态下,全部颜色都未使用
bitset<numColors> usedColors;
// something happens
usedColors.set(red);
usedColors.set(blue);
cout << "bitfield of used colors: " << usedColors << endl;
cout << "bitfield of unused colors: " << ~usedColors << endl;
// process if any color is used
if (usedColors.any())
{
for (int c = 0; c < numColors; ++c)
{ // 貌似只有遍历,而没有提供返回值为1的下标
if (usedColor[Color(c)])
{
//
}
}
}