最近在学习密码学,由于密码学涉及到的所有运算几乎都是位运算,编程时只使用数组来运算往往显得力力不从心
比如想要xor(亦或)往往得
for(i=0;i<n;i++)
c[i]=a[i] ^ b[i];
这样操作显得臃肿复杂。
于是我找到了c++处理位运算的一个强大的包--bitset
首先
bitset存储二进制数位。
bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一。
bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,表达式foo[3]访问了它的第4个元素,就像数组一样。
bitset有一个特性:整数类型和布尔数组都能转化成bitset。
如果你想定义一个存64位的数可以
bitset<64> a
实际编程时往往用
typedef bitset<64> word
Bitset的构造
唯一需要注意的是,bitset<>模板类虽然重载了中括号运算符,bs[0]表示的是将该数值转换为二进制时的最末尾元素,而非首位(其意义和数组并不相同)
std::bitset<8> bs;
//bs[0] = 1; // 0000 0001
//bs[7] = 1; // 1000 0000
- 默认无参构造
- 初始化全部位为0
Birset初始化
std::bitset<8> bs(7);
bs.to_string() // 0000 0111
std::bitset<8> bs(0x07);
bs.to_string() // 0000 0111
- 用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流 小值在右,大值在左 |
回到最开始的问题
有了bitset包,以后在进行密码学方面的编程时,
你可以以16进制初始化
bitset<8> = {0xC};
你可以轻松的进行按位亦或操作
bitset<16> a=0x4,b=0xf;
c=a^b;
随时转换进制的表示
bitset<16> a={0x4};
cout<<hex<<a.ulong(); //16进制输出
cout<<dec<<a.ulong(); //10进制输出
cout<<oct<<a.ulong(); //8进制输出