前言
程序中任何变量、函数等在计算机中都是以二进制的形式存储。对他们的操作其实都是对二进制位的操作。位运算就提供了对这些二进制位进行操作的方式。在C++中只有整形数据才能进行位运算,其他类型数据不能参与位运算。
背景
我们知道,二进制数有三种编码形式:原码、反码和补码。
原码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
反码:整数的数值位按位取反(0→1,1→0),符号位不变。(负整数)
补码:反码+1(负整数)。
注意: 正整数(原码=反码=补码) 负整数(反码和补码都需要计算)
整形数据在计算机中都是以补码的形式进行存储,而位运算也是对补码直接进行操作,而不是原码!
位运算
&(按位与运算)
“&” 为双目运算符,需要两个操作数,只有当两个操作数都为1时,结果才为1,其他情况都为0。
操作数1 | 操作数2 | & 运算结果 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
示例
#include<iostream>
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;
}
运行结果:
6 & 21 = 4
|(或运算)
“|” 为双目运算符,需要两个操作数,只有当两个操作数都为0时,结果才为0,其他情况都为1。
操作数1 | 操作数2 | | 运算结果 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
示例
#include<iostream>
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;
}
运行结果:
6 | 21 = 23
~ (按位取反)
“~” 为单目运算符,只需要1个操作数,操作数为1时,取反结果为0;操作数为0时,取反结果为1。
操作数1 | ~ 运算结果 |
---|---|
0 | 1 |
1 | 0 |
示例
#include<iostream>
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
^ (异或运算)
“^” 为双目运算符,需要两个操作数,当两个操作数不一样时,结果为1,两个操作数相同时为0。
操作数1 | 操作数2 | ^ 运算结果 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
示例
#include<iostream>
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;
}
运行结果:
621 ^ 1026 = 1647
<<(左移运算)
"<<"为双目运算符,形式为 “op1<<op2;”(op1为需要左移的数,op2为左移的位数)。在不考虑整数溢出的情况下,每左移一次,高位舍弃,低位补零。每左移一次,数值都为原来的2倍。
示例
#include<iostream>
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倍
}
运行结果:
621 << 1 = 1242
621 << 2 = 2484
>>(右移运算)
">>"为双目运算符,形式为 “op1>>op2;”(op1为需要右移的数,op2为右移的位数)。每右移一次,低位舍弃,高位补零。每右移一次,数值都为原来数值的一半。
示例
#include<iostream>
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倍
}
运行结果:
621 >> 1 = 310
621 >> 2 = 155