- 所谓位运算是指以二进制为对象的运算。在系统软件中,常常要处理二进制的问题,例如,将一个储存单元中的各个二进制左移或者右移一位、两个数按位相加等。C语言提供位运算的功能,与其他高级语言相比,它显然具有很大的优越性
运算符 | 含义 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 按位取反 |
<< | 左移 |
>> | 右移 |
说明
参加运算的两个数据按二进制位进行“与”运算,如果两个相应的二进制位都为1,则该位的结果值为1;否则为0.即
0 & 0 = 0 ,0 & 1 =0,1 & 1 = 0,1 & 1 = 1.
例如,7 & 5 并不是等于12,应该是进行"按位与操作"
0 0 0 0 0 1 1 1 (7)
(&) 0 0 0 0 0 1 0 1 (5)
----------------------
0 0 0 0 0 1 0 1 (5)
因此,7 & 5的值为5。如果参加”&“运算的是负数(如 -7 & -5),则以补码的形式表示为二进制数,然后按位进行”与“操作
注意,&&是逻辑与运算符,7&&5的值为1因为非0的数值按”真“处理,逻辑与的结果是”真“,以1表示。而&是按位与,7&5的结果是5.
按位与的一些特殊用途
(1)清零。
如果想将一个单元清零,即使其全部二进制数为0,只要找一个二进制数,其中各个位符合以下条件:原来的数中为1的数,新数中相应位为0。然后使二者进行&运算,即可达到清零目的。
例如,原有数为00101011,另外一个数,设他为10010100
0 0 1 0 1 0 1 1
(&) 1 0 0 1 0 1 0 0
----------------------
0 0 0 0 0 0 0 0
(2)取一个数中某些指定位
如有一个整数a,想要其中的低字节。只需将a与 八进制(377)按位与即可,如
a: 10 10 11 00
b: 11 11 11 11
------------------
c: 10 10 11 00
(3)要想将哪一位保留下来,就与一个数进行&运算,此数在该位取1.例如,有一个数01010100,想要其中左边第3,4,5,7,8位保留下来,可以这么运算:
0 1 0 1 0 1 0 0
(&) 0 0 1 1 1 0 1 1
-----------------------
0 0 0 1 0 0 0 0
可以看到得到的结果的数为(16)
其中第3,4,5,7,8位就是01010100的第3,4,5,7,8位
其他位为0。
按位或运算的规则是:两个对应的二进制位中只要有一个位1,改位的结果值为1.即例如:
0 0 1 1 0 0 0 0
(|) 0 0 0 0 1 1 1 1
-------------------------
0 0 1 1 1 1 1 1
低四位全为1.如果想使一个数a的低四位改为1,只须将a与017进行按位与或运算即可。
按位或运算常用来对一个数据的某些位定值为1,例如,a是一个整数,有表达式:a|0377,则低八位全置为1,高八位保留原样。
异或运算符”^”也称为XOR运算符。它的规则是:若参加运算的两个二进制位异号,则得到1(真),若同号,则结果为0(假)。即
0 0 1 1 1 0 0 1
(^) 0 0 1 0 1 0 1 0
-------------------------
0 0 0 1 0 0 1 1
下面举例说明异或运算符的应用。
(1)使特定位翻转。
假设有 0111010,想使其第四位翻转,即1变为0,0变为1.可以将它与00001111进行异或(^)运算,即:
0 1 1 1 1 0 1 0
(^) 0 0 0 0 1 1 1 1
-------------------------
0 1 1 1 0 1 0 1
结果中的第四位正好是原数第四位的翻转。
要使哪几位翻转就将与其进行^运算的数在该几位置为1(其他位0)即可。
(2)与0向^,保留原值
例如:012 ^ 0 0= 012
0 0 0 0 1 0 1 0
(^) 0 0 0 0 0 0 0 0
-------------------------
0 0 0 0 1 0 1 0
因为原数中的1与0进行^运算得到1,0^0得0,故保留原数。
(3)交换两个值,不用临时变量
假如a=3,b=4.想将a和b 的值互换,可以用以下赋值语句实现:
a = a ^ b;
b = b ^ a;
a = a ^ b;
即:
a= 0 1 1
(^) b= 1 0 0
--------------
a= 1 1 1
(^) b= 1 0 0
-------------
b= 0 1 1
(^) a= 1 1 1
-------------
a= 1 0 0
“~”是一个单目运算符,用来对一个二进制数按位取反,即将0变1,将1变0。
运算符的应用,经常运用在想要某个最低一位为(如寄存器的操作),可以用: a=a& ~1
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1
(&) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
--------------------------------------
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0
即先进行~a操作,然后进行&操作
此外,~ 运算符的优先级比算术运算符、关系运算、逻辑运算符和其他位运算符都高
“<<“用来将一个数的各二进制位全部左移若干位,例如:
将a的二进制数左移2位,右补0.若a=15,即二进制数的00001111,左移2位得00111100,即得到十进制数60.高位左移后溢出,舍弃。
0 0 0 0 1 1 1 1
(<<2,左移两位)
----------------------------------
(溢出舍弃)0 0| 0 0 1 1 1 1 |0 0(右补0)
左移一位相当于该数乘以2,左移2位相当于该数乘以2²=4,左移比乘法快的多,有些C编译程序自动将乘2的运算用左移一位来实现,将乘2的n次方的幂运算处理为左移n位。
a>>2表示将a的各二进制位右移2为,移到右端的低位被舍弃,对无符号数,高位补0。
例如,a=017时,a的值用二进制形式表示为 00001111。
0 0 0 0 1 1 1 1
(>>2,右移两位)
----------------------------------
(左补0)0 0|0 0 0 1 1 |1 1(此两位舍弃)
在右移时,需要注意符号位问题。对无符号位数,右移时左边高位补0;对于有符号位的数,如果原来符号位为0(该数为正),则左边也补0;如果符号位为原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的补0,有的系统补1。补0的称为”逻辑右移“,即简单右移,不考虑数的符号问题,补1的为 ”算术右移“(保持原有的符号)。
位运算符与赋值运算符可以组合成复合赋值运算符,如:&=,|=,>>=,<<=,^=等。
例如,a&=b 相当于 a=a&b, a<<=2相当于a=a<<2。
如果两个数据长度不同(例如short和int型)进行位运算时(如a&b,而a为short型,b为int型),系统会自动将二者按右端对齐。如果a为正数,则左侧16位补满0;若a为负数,左端应补满1;如果a为无符号整数型,则左侧添满0。
原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/90566.html