操作二进制位串的工具

本文介绍了二进制位串的操作,包括位运算符如移位、位求反、位与、位或、位异或,以及C++中的bitset类。位运算符主要针对整数类型,位串从右至左编号,bitset提供了初始化、检测和设置位的方法,并支持位运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

操作二进制位串的工具

一.位运算符

  • 位运算符作用于整数类型的对象,并把运算对象看成是二进制位的集合。
  • 它提供检查和设置二进制位的功能。

运算符功能用法
~位求反~expr
<<左移expr1 << expr2
>>右移expr1 >> expr2
&位与expr1 & expr2
^位异或expr1 ^ expr2
|位或expr1

- 符号位的处理没有规定,因此建议仅用于处理无符号类型
- 一般来说,如果运算对象是”小整型“,则它的值会被自动提升成较大的整数类型。运算对象可以是带符号的,且为负,则如何处理”符号位“依赖于机器。而且此时左移可能会改变符号位的值,是一种未定义行为。
- 整型提升:任何使用了char,short,整型位域或者枚举类型的表达式,(bool、char、signed char、unsigned char、short、unsigned short等小于int的类型),如果装得下,都会被提升成int类型;否则提升为unsigned int。较大的char(wchar_t、char_16_t、char_32_t)则提升为int–unsigned long long中刚好能装下其所有可能的一种


移位运算符

对运算对象执行基于二进制的移动操作

unsigned char bits = 0233;// 0233是八进制的字面值
内存中
0X123420X123430X123440X12345
其 余 的 数 据其 余 的 数 据其 余 的 数 据1 0 0 1 1 0 1 1
bits << 8;// bits提升为int,向左移8位
0X123420X123430X123440X12345
0 0 0 0 0 0 0 00 0 0 0 0 0 0 01 0 0 1 1 0 1 10 0 0 0 0 0 0 0
bits << 31;// 向左移动31位,左边超出边界的位被丢弃
0X123420X123430X123440X12345
1 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 0
bits >> 3;// 向右移3位,最右边3位被丢弃
0X123420X123430X123440X12345
0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 1 0 0 1 1

左移运算符在右侧插入0。右移运算符的行为依赖于左侧的运算对象的类型,这里操作的是无符号类型,在左侧插入0,如果运算对象是带符号类型,在左侧插入符号位的副本或0,如何选择视情况而定


位求反运算符

将运算对象逐位求反后生成一个新值

~bits;// char先提升为int,高位添0,然后逐位求反
0X123420X123430X123440X12345
1 1 1 1 1 1 1 11 1 1 1 1 1 1 11 1 1 1 1 1 1 10 1 1 0 0 1 0 0

位与、位或、位异或运算符

&、|、^在两个运算对象上执行相应的逻辑操作

unsigned char b1 = 0145;
内存中
0X123420X123430X123440X12345
其 余 的 数 据其 余 的 数 据其 余 的 数 据0 1 1 0 0 1 0 1
unsigned char b2 = 0257;
0X123420X123430X123440X12345
其 余 的 数 据其 余 的 数 据其 余 的 数 据1 0 1 0 1 1 1 1
b1 & b2
0X123420X123430X123440X12345
0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 1 0 0 1 0 1
b1 | b2
0X123420X123430X123440X12345
0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 01 1 1 0 1 1 1 1
b1 ^ b2
0X123420X123430X123440X12345
0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 01 1 0 0 1 0 1 0

二.bitset

  • #include < bitset >
  • 位串可以作为开关(0/1)的集合
  • 位运算符同样可以作用于bitset
  • 二进制位串从0开始编号,从右至左,低位到高位。

bitset的初始化

bitset类是一种类模板;而与vector不一样的是bitset类型对象的区别仅在其长度而不在其类型。在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值:

bitset<8> bitvec(1U); // 8位;低位为1,其余为0:00000001;

构造函数介绍
bitset<n> b;b有n位,默认为0
bitset<n> b(u);b是u低n位的拷贝,若n>u的长度,则b高位置0
bitset<n> b(s);b是string对象s中含有的位串的副本
bitset<n> b(s,pos,n);b是s中从位置pos开始的n个位的副本
bitset<n> b(s,pos,m,zero,one);同上,但s只能包含0或1
bitset<n> b(cp,pos,m,zero,one);cp是指向字符数组或者c风格字符串的指针

接受string或字符指针的构造函数是explicit(只能直接初始化)
zero和one可以替换为其他char型字符


bitset的操作

bitset操作定义了多种检测或设置一个或多个二进制位的方法,同时bitset还支持位运算符(将bitset对象看做一个unsigned数)。

操作介绍
b.any()b中是否存在置为1的二进制位?
b.all()b中所有位都置为1了吗?
b.none()b中不存在置为1的二进制位吗?
b.count()b中置为1的二进制位的个数
b.size()返回b中二进制位的个数
b[pos]访问b中在pos处的二进制位
b.test(pos)b中在pos处的二进制位是否为1?
b.set()把b中所有二进制位都置为1
b.set(pos,v)把b中在pos处的二进制位置为bool值v,v默认为true
b.reset()把b中所有二进制位都置为0
b.reset(pos)把b中在pos处的二进制位置为0
b.flip()把b中所有二进制位逐位取反
b.flip(pos)把b中在pos处的二进制位取反
b.to_ulong()用b中同样的二进制位返回一个unsigned long值,如果b中的位模式不能放入指定结果类型,则抛出overflow_error
b.to_string(zero,one)返回一个string,表示b中的位模式。zero和one默认为0,1
os << b把b中的位集输出到os流
is >> b从is读取字符存入b。当下一个字符不是1或0,或已经读b.size()个,读取停止

example

    #include <iostream>
    #include <bitset>
    #include <string>

    int main()
    {
    // 验证-0(例如8位char型就是10000000)是有符号数的下限:先获得 -0,再格式输出,通过输出值来判断
    // 获得 -0
    char zero = 0;
    std::bitset<8> bits(zero);

    if (bits.none())    // bits位串中没有1
        std::cout << " no 1 in bits: " << bits << std::endl;
    else
        std::cout << " have 1 in bits: " << bits << std::endl;

    bits[7] = 1;    // 将符号位位赋值为1

    std::cout << bits.to_string('1','2')<<std::endl;
    char key = 0;

    if (bits.none())
        std::cout << " no 1 in bits: " << bits << std::endl;
    else
    {
        std::cout << " have 1 in bits: " << bits << " as a integer is: " << bits.to_ulong() << std::endl;
        key = bits.to_ulong();  // 位串转换为无符号数,再转换为有符号数
    }
    // 格式输出
    char compare = -128;
    std::cout << key << compare << std::endl;

    system("pause");
    return 0;
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值