《C++ Primer Plus》E1 按位运算符 -笔记
《C++ Primer Plus》E1 按位运算符 -笔记
0 首先要知道的事情
每个数的二进制形式都是0和1的排列组合,二进制基数为2,即每进一位,高位上的值的含义都比低一位上的值的含义多了2倍。如二进制数\(1000\)表示的是\(2^3=8\),二进制数\(0100\)表示的是\(2^2=4\)。
还有一种角度,可以把每个位置上的0和1看成“开关”的开或者关的一种状态。
1 移位运算
一个二进制数是0和1的组合排列,将一个具体的二进制数每个位置上的值(0或1)都向左边的n个位置移动,得到的新的数字的过程,就是左移位的操作。
由于2进制以2作为基数,每升高一位值比原来扩大2倍,那么左移n位,新值相对于原值扩大了\(2^n\)倍。
在C++中,用<<
表示左移操作,
- 用法:
被左移的数 << 左移的位数n
- 返回值:\(被左移的数*2^n\)
同样的,右移将被操作的数缩小了\(2^n\)倍,在C++中,用>>
表示左移操作,
- 用法:
被右移的数 << 右移的位数n
- 返回值:\(被右移的数/2^n\)
2 逻辑按位运算符
逻辑运算符是对某个变量进行操作,如或与非,|、&、!,逻辑按位运算符的不同在于对二进制上的每个位置分别处理。0和1可以看成是每个位置上的两种状态。
- 位反
位反:~
,作用是将原来位置上的值变为相反的值,得到的新值是原值的补值。如:
一个字节(byte)有8位(bit),一个位有0和1两种值
2个字节(16位)的int类型的13,其位反
int x=13; //x=0000000000001011
x=~x; //x=1111111111110100
- 按位运算符\(OR\)
按位或运算:|
,两个二进制数,在某个未知数,至少有1个1时,新值的该位置上为1,否则,为0,即有1为1,无1为0。
逻辑按位运算符可以和赋值符号=一起应用,表示先对结合符号左侧和右侧的数进行逻辑按位运算操作,然后将表达式的值赋给结合符号左侧的变量。
a |= b
等价于a = a|b
- 按位运算符\(XOR\)(异或)
按位异或运算:^
,对两个整数操作,对应位置上如果是不同的值,即,其中一个为0,另一个为1时,结合后的新值为1,否则,如果对应位置上的值相等,结合后的新值为0。
异或重在异,异代表不同,不同则为1,异为1,同为0。
异或有很多有趣的性质,比如完成两个数值的交换,而不使用第三个变量:
a=a^b; //此时a1=a0^b0
b=a^b; //此时b1=a1^b0=a0^b0^b0=b0^a0^b0=a0,b的值已经变成了原来a0的值
a=a^b; //此时a2=a1^b1=a0^b0^b1=a0^b0^a0=b0,a的值变成了b最初的值b0
- 归零律:
a^a=0
- 恒等律:
a^0=a
- 交换律:
a^b=b^a
- 自反律:
a^b^a=b
- 按位运算符\(AND\)(与)
按位与运算:&
,两个二进制数,在同一个位置上,同为1则为1,有0存在时,则为0,有0为0,无0为1。
3 按位运算符对具体位置的开关(0,1状态)控制
用a
表示被操作的二进制数,用bit
表示特定位置上的值,例如00001000
,表示从右到左的第4
位上的值为1
,十进制的值为\(2^{4-1}=2^3=8\),若用i
表示从右向左的位数,则bit= 1 <<(i-1)
。
- 打开位
将目标位置上的值设置成1。
a |= bit;// <-> a |= ( 1 << (i-1) )
- 切换位
将目标位置上的值设置成原值的相反状态,即0->1,1->0。
a ^= bit;// <-> a ^= ( 1 << (i-1) )
- 关闭位
将目标位置上的值设置成0。
a &= ~bit;// <-> a &= ~( 1 << (i-1) )
- 检验位
测试目标位置上的值是否为1(不管其他位置的值)。
if ( a & bit == bit) //<-> if ( a & bit)