【STL】C++标准库bitset类型

    bitset用于处理二进制位集。是一种类模板。

  1. #include<bitset>  
  2. using std::bitsset  
#include<bitset>
using std::bitsset

1. 定义和初始化

      在定义bitset时,要明确bitset是多少位,须在尖括号中制定它的长度值。

  1. bitset<32> bitvec;  
bitset<32> bitvec;

给定的长度必须是常量表达式,也即必须定义为整型字面值常量或const对象。

  (1). 用unsigned之初始化bitset对象

        unsigned long值将转换为二进制的位模式,若bitset类型长度大于unsigned long的二进制位数,则其余高阶位置0;若小于,则使用unsigned long的低阶位,超过bitset的高阶位被丢弃。

注:低阶位-高阶位

bitset:在32位的bitset对象上为例,以0开始的位串是低阶位(low-order bit),以31 位结束的位串是高阶位(hight-order bit)。

word(机器字):在在32位的unsigned long机器上,在不同体系结构的机器上应该有不同的存储方式。引自英文原版C++ Primer 4中【On a machine with 32-bit unsigned long s, the hexadecimal value 0xffff is represented in bits as a sequence of 16 ones followed by 16 zeroes. (Each 0xf digit is represented as 1111 .)】所说的存储方式为低字节在前,高字节在后。以0xffff为例,在机器内的存储方式为:11111111111111110000000000000000,从低阶–>高阶。

关键概念:计算机的内存存储方式

计算机的内存存储方式由CPU决定,不过为了兼容性,现在AMD和INTEL都是用相同的方式存放:低字节放在前面,高字节放在后面。 要明白,后面的内存地址比前面大1,也就是低字节放在地址小的空间,高字节放在地址大的空间。
综上所述:无论对于bitset还是计算机机器字的内存存储方式(其实是同一个),只要记住低阶对应于内存地址较小小的空间,高阶对应于内存地址较大的空间。(低対低,高对高,一一对应)。

知道了以上这些,对于bitset的存储方式,就很容易理解了。例:

  1. //1. 用unsigned 值初始化  
  2. bitset<16> bitvec1(0xfffa);  
  3. bitset<32> bitvec2(0xffff);  
  4. cout<<”bitvec1:”<<bitvec1<<endl;  
  5. cout<<”bitvec2:”<<bitvec2<<endl;  
   //1. 用unsigned 值初始化
    bitset<16> bitvec1(0xfffa);
    bitset<32> bitvec2(0xffff);
    cout<<"bitvec1:"<<bitvec1<<endl;
    cout<<"bitvec2:"<<bitvec2<<endl;
输出:bitvec1:1111111111111010
           bitvec2:00000000000000001111111111111010

这时奇怪的事发生了,输出并不是期待的顺序,而是相反的。这里还要说的是,bitset实现的<<操作符输出时,将会从bitset的高阶–>低阶输出(更自然)。因此若用for循环从0开始输出就会是实际存储的顺序了。

  1. cout<<“bitvec1(RAW):”<<bitvec1<<endl;  
  2. cout<<”bitvec1(FOR):”;  
  3.    for(size_t bs1 = 0;bs1!=bitvec1.size();bs1++)  
  4. {  
  5.     cout<<bitvec1[bs1];  
  6. }  
  7. cout<<endl;  
  8.   
  9. cout<<”bitvec2(RAW):”<<bitvec2<<endl;  
  10. cout<<”bitvec2(FOR):”;  
  11.    for(size_t bs1 = 0;bs1!=bitvec2.size();bs1++)  
  12. {  
  13.     cout<<bitvec2[bs1];  
  14. }  
  15. cout<<endl;  
    cout<<"bitvec1(RAW):"<<bitvec1<<endl;
    cout<<"bitvec1(FOR):";
    for(size_t bs1 = 0;bs1!=bitvec1.size();bs1++)
    {
        cout<<bitvec1[bs1];
    }
    cout<<endl;

    cout<<"bitvec2(RAW):"<<bitvec2<<endl;
    cout<<"bitvec2(FOR):";
    for(size_t bs1 = 0;bs1!=bitvec2.size();bs1++)
    {
        cout<<bitvec2[bs1];
    }
    cout<<endl;

输出为:bitvec1(RAW):1111111111111010
               bitvec1(FOR):0101111111111111
               bitvec2(RAW):00000000000000001111111111111010
               bitvec2(FOR):01011111111111110000000000000000

      (2). 用string对象初始化bitset对象

当用string对象初始化bitset对象时,string对象直接表示为位模式。从string对象读入位集的顺序是从右到左。

  1. //2. 用string对象初始化  
  2. string strval(”1100”);  
  3. bitset<8> bitvec4(strval);  
  4. cout<<”bitvec4(RAW):”<<bitvec4<<endl;  
  5.   
  6. cout<<”bitvec4(FOR):”;  
  7. for(size_t bs = 0;bs!=bitvec4.size();bs++)  
  8. {  
  9.     cout<<bitvec4[bs];  
  10. }  
    //2. 用string对象初始化
    string strval("1100");
    bitset<8> bitvec4(strval);
    cout<<"bitvec4(RAW):"<<bitvec4<<endl;

    cout<<"bitvec4(FOR):";
    for(size_t bs = 0;bs!=bitvec4.size();bs++)
    {
        cout<<bitvec4[bs];
    }
输出:bitvec4(RAW):00001100

          bitvec4(FOR):00110000

上述string对象strval可看成字符数组{‘1’, ‘1’, ‘0’, ‘0‘}.

从上可以看出,string对象与bitset对象之间是反向转化的:string对象的最右边字符(既下标最大的那个字符)用来初始化bitset对象的低阶位(即下标为0的位)。这是与用unsigned值初始化bitset对象不同的。即不是遵从低阶高阶一一对应的。

   截取子串作为初始值。

  1. string str(“1111111000000011001101”);  
  2. bitset<32> bitvec5(str,5,4);  
  3. bitset<32> bitvec6(str,str.size()-4);  
  4. cout<<”bitvec5:”<<bitvec5<<endl;  
  5. cout<<”bitvec6:”<<bitvec6<<endl;  
   string str("1111111000000011001101");
    bitset<32> bitvec5(str,5,4);
    bitset<32> bitvec6(str,str.size()-4);
    cout<<"bitvec5:"<<bitvec5<<endl;
    cout<<"bitvec6:"<<bitvec6<<endl;

输出:bitvec5:00000000000000000000000000001100
         bitvec6:00000000000000000000000000001101

bitvec5用str[5]开始的4个字符子串来初始化。

如果省略第3个参数,则取从开始位置一直到string对象末尾的所有字符,bitvec6用str末尾的4位来初始化。

2. bitset 对象上的操作

       (1). 测试整个bitset对象

  1. bool is_set = bitvec6.any();    //是否存在置为1 的位  
  2. bool is_not_set = bitvec6.none();   //是否不存在置为1的数  
  3.   
  4. size_t bits_set = bitvec6.count();  //置为1的数  
  5. cout<<”bits_set: ”<<bits_set<<endl;  
  6.   
  7. size_t sz = bitvec6.size(); //返回bitset对象中对应的二进制位的个数  
  8. cout<<”bits_size: ”<<sz<<endl;  
  bool is_set = bitvec6.any();    //是否存在置为1 的位
    bool is_not_set = bitvec6.none();   //是否不存在置为1的数

    size_t bits_set = bitvec6.count();  //置为1的数
    cout<<"bits_set: "<<bits_set<<endl;

    size_t sz = bitvec6.size(); //返回bitset对象中对应的二进制位的个数
    cout<<"bits_size: "<<sz<<endl;
        (2). 访问bitset 对象的位

   可以用下标操作来读写某个索引的二进制位。

  1. //访问bitset对象中的位  
  2. for(int index = 0;index != bitvec6.size(); index++)  
  3. {  
  4.     bitvec6[index] = 1;  
  5. }  
  6. //还可调用set,reset等操作  
  7. for(int index = 0;index != bitvec6.size();index++)  
  8. {  
  9.     bitvec6.set(index);  
  10. }  
  11. //测试  
  12. if(bitvec6.test(3))  
  13. {  
  14. }  
  15. //等价于   
  16. if(bitvec6[3])  
  17. {  
  18. }  
  //访问bitset对象中的位
    for(int index = 0;index != bitvec6.size(); index++)
    {
        bitvec6[index] = 1;
    }
    //还可调用set,reset等操作
    for(int index = 0;index != bitvec6.size();index++)
    {
        bitvec6.set(index);
    }
    //测试
    if(bitvec6.test(3))
    {
    }
    //等价于 
    if(bitvec6[3])
    {
    }
      (3). 对整个bitset对象进行设置
  1. bitvec5.set();  //设置所有  
  2. bitvec5.reset();   //重置所有  
  3.    //取反  
  4. bitvec5.flip(2);  //对某位取反  
  5. bitvec5[2].flip();  
  6. bitvec5.flip(); //对所有位取反  
  bitvec5.set();  //设置所有
    bitvec5.reset();   //重置所有
    //取反
    bitvec5.flip(2);  //对某位取反
    bitvec5[2].flip();
    bitvec5.flip(); //对所有位取反
     (4). 获取bitset 对象的值

to_long 操作返回一个unsigned long 值,该值与bitset的位模式存储值相同。仅当bitset 类型的长度小于或等于unsigned long 的长度,才可用to_long操作:

  1. bitset<132> bitvec7(124);  
  2. cout<<”bitvec7: ”<<bitvec7<<endl;  
  3. unsigned long ulong = bitvec7.to_ullong();  
  4. cout<<ulong<<endl;  
 bitset<132> bitvec7(124);
    cout<<"bitvec7: "<<bitvec7<<endl;
    unsigned long ulong = bitvec7.to_ullong();
    cout<<ulong<<endl;
 如果bitset对象包含的二进制位数超过 unsigned long 的长度,将会产生运行时异常。

     (5) .使用位操作符

bitset 也支持内置的位操作符,这些操作符只适用于整型操作数。

  1. cout<<“bitvec7: ”<<(bitvec7&=0xf)<<endl;  
   cout<<"bitvec7: "<<(bitvec7&=0xf)<<endl;


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值