在计算机内存中一个数是以它的二进制序列的补码形式保存,而计算机也只认识二进制数0与1。而对于一个数的二进制序列,在C语言中有专门的位运算符对它进行操作。(注意:所有的位运算符都是对于补码进行操作的,以下所说的二进制序列均对应的是补码)
1.按位与(&)
首先,按位与是对两个二进制序列的每一位一一对应进行“与”的运算,大致规则是有0为0,全1为1。【(0000 1111)&(0000 1010 )=0000 1010】
而根据按位与的运算规则,我们可以将它用在这几方面:
(1)清零:根据运算规则,我们可以给定一个数,只要它符合它的二进制序列在要进行清零操作的那个数上为“1”的对应位为“0”即可(甚至直接给定0这个数),将它与目标数进行按位与运算,即可进行清零。
举例:对15这个数进行清零(15的二进制序列为0000 1111),只要将15和0按位与即可【15&0】
0000 1111
0000 0000
------------------
0000 0000
(2)保留一个数的二进制序列中的某一部分:根据运算规则,可以给定一个数,只要符合其二进制序列在目标数要保留的部分全为“1”即可,将两个数进行按位与运算即可保留。
举例:要保留二进制序列“00110000 01010101”中的“01010101”部分,只要将原序列和“00000000 11111111”进行按位与即可。
00110000 01010101
00000000 11111111
---------------------------------
00000000 01010101
(3)去掉一个数二进制序列中最低位的“1”:根据运算规则,对于一个数x可以将它和x-1进行按位与运算,即可消去最低位的“1”。【x&(x-1)】
举例:x的二进制序列为00001111 00000000,那么(x-1)的二进制序列为00001110 11111111
00001111 00000000
00001110 11111111
-------------------------------
00001110 00000000
2.按位或(|)
首先按位或是对两个数的二进制序列的每一位一一对应进行“或”运算,大致规则是有1为1,全0位0
而根据运算规则,按位或有下面的应用:
将一个数的指定部分改为“1”:我们可以给定一个数,而这个数只要满足与目标数的指定部分相对应的位上为“1”即可。
举例:将1111 0000改为1111 1111,给定0000 1111
1111 0000
0000 1111
----------------
1111 1111
3.左移(<<)和右移(>>)
x<<k:将x左移k位,相当于将x乘2的k次方【这个很容易理解,假设原本1是在最低位上的,表示2的0次方,将它进行左移k位,那么这个1就移动至从最低位开始数的第k+1位,即表示2的k次方,是原来的2的k次方倍】
x>>k:将x右移k位,相当于将x除2的k次方【原理与左移相同】
而对于二进制序列的而言,左移没什么,就是向左移相应位,然后在右边补0;而对于右移来说,就要分为逻辑移位和算术移位。
逻辑移位:在右移时,右边丢弃,左边补符号位
算术移位:在右移时,右边丢弃,左边补0
而究竟是逻辑移位还是算术移位,这个要取决于编译器,而大体上,无符号数都是算术移位,而对于有符号数,则基本上遇到的百分之八九十是逻辑移位。
4.按位异或(^)
按位异或是将两个数的二进制序列一一对应,如果相应的位上同为0或同为1,那么结果在这个位上就是0,反之,如果相应的位上的数不同,那么结果在这个位上就为1。【简单来说就是相同为0,不同位1】
举例:15^10=5
00000000 00001111
00000000 00001010
--------------------------------
00000000 00000101
而对于多个数进行位运算而言,两个相等的数按位异或结果为0,而对于多步的按位异或,则它们之间相互抵消。
举例:a^b^a=b
5.按位取反(~)
按位取反没有什么,只是将二进制序列上每一位上的1变为0,0变为1即可