《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)