• C++学习——位操作


    前言

    程序中任何变量、函数等在计算机中都是以二进制的形式存储。对他们的操作其实都是对二进制位的操作。位运算就提供了对这些二进制位进行操作的方式。在C++中只有整形数据才能进行位运算,其他类型数据不能参与位运算。

    背景

    我们知道,二进制数有三种编码形式:原码、反码和补码
    原码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
    反码:整数的数值位按位取反(0→1,1→0),符号位不变。(负整数)
    补码:反码+1(负整数)。
    注意: 正整数(原码=反码=补码)      负整数(反码和补码都需要计算)
    整形数据在计算机中都是以补码的形式进行存储,而位运算也是对补码直接进行操作,而不是原码

    位运算

    &(按位与运算)

       “&” 为双目运算符,需要两个操作数,只有当两个操作数都为1时,结果才为1,其他情况都为0。

    与运算规则
    操作数1操作数2& 运算结果
    000
    010
    100
    111

    示例

    #include
    using namespace std;
    int main(){
    	int a=6;//6的补码:  0000 0000 0000 0000 0000 0000 0000 0110
    	int b=21;//21的补码:0000 0000 0000 0000 0000 0000 0001 0101
    	int c=a&b;//4的补码:0000 0000 0000 0000 0000 0000 0000 0100
    	cout<<"6 & 21 = "<<c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:

    6 & 21 = 4
    
    • 1

    |(或运算)

       “|” 为双目运算符,需要两个操作数,只有当两个操作数都为0时,结果才为0,其他情况都为1。

    或运算规则
    操作数1操作数2| 运算结果
    000
    011
    101
    111

    示例

    #include
    using namespace std;
    int main(){
    	int a=6;//6的补码:   0000 0000 0000 0000 0000 0000 0000 0110
    	int b=21;//21的补码: 0000 0000 0000 0000 0000 0000 0001 0101
    	int c=a|b;//23的补码:0000 0000 0000 0000 0000 0000 0001 0111
    	cout<<"6 | 21 = "<<c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:

    6 | 21 = 23
    
    • 1

    ~ (按位取反)

       “~” 为单目运算符,只需要1个操作数,操作数为1时,取反结果为0;操作数为0时,取反结果为1。

    取反运算规则
    操作数1~ 运算结果
    01
    10

    示例

    #include
    using namespace std;
    int main(){
    	int a=1;//1的补码:  0000 0000 0000 0000 0000 0000 0000 0001
    	int b=~a;//-2的补码:1111 1111 1111 1111 1111 1111 1111 1110
    	cout<<"~1 = "<<b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:

    ~1 = -2
    
    • 1

    ^ (异或运算)

       “^” 为双目运算符,需要两个操作数,当两个操作数不一样时,结果为1,两个操作数相同时为0。

    异或运算规则
    操作数1操作数2^ 运算结果
    000
    011
    101
    110

    示例

    #include
    using namespace std;
    int main(){
    	int a=621;//621的补码:   0000 0000 0000 0000 0000 0010 0110 1101
    	int b=1026;//1026的补码: 0000 0000 0000 0000 0000 0100 0000 0010
    	int c=a^b; //1647的补码: 0000 0000 0000 0000 0000 0110 0110 1111
    	cout<<"621 ^ 1026 = "<<c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:

    621 ^ 1026 = 1647
    
    • 1

    <<(左移运算)

    "<<"为双目运算符,形式为 “op1<”(op1为需要左移的数,op2为左移的位数)。在不考虑整数溢出的情况下,每左移一次,高位舍弃,低位补零。每左移一次,数值都为原来的2倍。

    示例

    #include
    using namespace std;
    int main(){
    	int a=621;	  //	621补码: 0000 0000 0000 0000 0000 0010 0110 1101
    	int b=a<<1;	//	1242补码:0000 0000 0000 0000 0000 0100 1101 1010
    	int c=a<<2;	//	2484补码:0000 0000 0000 0000 0000 1001 1011 0100
    	cout<<"621 << 1 = "<<b<<endl;//左移1次 变为原数值的2倍
    	cout<<"621 << 2 = "<<c;      //左移2次 变为原数值的4倍
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:

    621 << 1 = 1242
    621 << 2 = 2484
    
    • 1
    • 2

    >>(右移运算)

    ">>"为双目运算符,形式为 “op1>>op2;”(op1为需要右移的数,op2为右移的位数)。每右移一次,低位舍弃,高位补零。每右移一次,数值都为原来数值的一半。

    示例

    #include
    using namespace std;
    int main(){
    	int a=621;	  //	621补码: 0000 0000 0000 0000 0000 0010 0110 1101
    	int b=a>>1;	//	310补码: 0000 0000 0000 0000 0000 0001 0011 0110
    	int c=a>>2;	//	155补码: 0000 0000 0000 0000 0000 0000 1001 1011
    	cout<<"621 >> 1 = "<<b<<endl;//右移1次 变为原数值的1/2倍
    	cout<<"621 >> 2 = "<<c;      //右移2次 变为原数值的1/4倍
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:

    621 >> 1 = 310
    621 >> 2 = 155
    
    • 1
    • 2
  • 相关阅读:
    java废旧物品回收管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    如何创建Facebook的WhatsApp广告
    【Android】WebView请求HttpRequest和HttpResponse
    项目快讯|深汕特别合作区气膜羽毛球馆正式开工
    qmake eval(string) 函数
    关于“语雀故障公告”的学习与思考:可监控!可灰度!可回滚!
    蓝桥杯官网练习题(幸运数字)
    C语言:数组名和数组地址
    5-2:Kafka入门
    交换高级特性 —— DHCP snooping(DHCP欺骗泛红攻击)
  • 原文地址:https://blog.csdn.net/mitongxue/article/details/126196365