C语言中的位运算

C语言中的位运算

所谓位运算是指以二进制为对象的运算。在系统软件中,常常要处理二进制的问题,例如,将一个储存单元中的各个二进制左移或者右移一位、两个数按位相加等。C语言提供位运算的功能,与其他高级语言相比,它显然具有很大的优越性。

运算符含义
&按位与
I按位或
^按位异或
~按位取反
<<左移
>>右移

说明
1.位运算符中除“~”以外,均为二目运算符,即要求两侧各有一个运算量,如a&b。
2.参加位运算的对象只能是整形或字符型的数据,不能为实型数据。

1.1 “按位与”运算

参加运算的两个数据按二进制位进行“与”运算,如果两个相应的二进制位都为1,则该位的结果值为1;否则为0.即

0 & 0 = 00 & 1 =01 & 1 = 01 & 1 = 1.
例如,7 & 5 并不是等于12,应该是进行"按位与操作"
       0 0 0 0 0 1 1 17)
(&0 0 0 0 0 1 0 15----------------------
       0 0 0 0 0 1 0 15

因此,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.2 按位或运算

按位或运算的规则是:两个对应的二进制位中只要有一个位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,高八位保留原样。

1.3 ”异或“运算

异或运算符”^”也称为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

因为原数中的10进行^运算得到1,0^00,故保留原数。

(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

1.4 “取反”运算

“~”是一个单目运算符,用来对一个二进制数按位取反,即将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操作,然后进行&操作

此外,~ 运算符的优先级比算术运算符、关系运算、逻辑运算符和其他位运算符都高

1.5 左移运算

“<<“用来将一个数的各二进制位全部左移若干位,例如:

将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位。

1.6 右移运算

a>>2表示将a的各二进制位右移2为,移到右端的低位被舍弃,对无符号数,高位补0。
例如,a=017时,a的值用二进制形式表示为 00001111。

                 0 0 0 0 1 1 1 1>>2,右移两位)
----------------------------------
  (左补00 0|0 0 0 1 1 |1 1(此两位舍弃) 

右移一位相当于除以2,右移n位相当于除以2的n次方。

在右移时,需要注意符号位问题。对无符号位数,右移时左边高位补0;对于有符号位的数,如果原来符号位为0(该数为正),则左边也补0;
如果符号位为原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的补0,有的系统补1。
补0的称为”逻辑右移“,即简单右移,不考虑数的符号问题,补1的为 ”算术右移“(保持原有的符号)。

1.7位运算赋值运算符

位运算符与赋值运算符可以组合成复合赋值运算符,如: &=,|=,>>=,<<=,^=等。
例如,a&=b 相当于 a=a&b, a<<=2相当于a=a<<2。

1.8不同长度的数据进行位运算

如果两个数据长度不同(例如short和int型)进行位运算时(如a&b,而a为short型,b为int型),系统会自动将二者按右端对齐如果a为正数,则左侧16位补满0;若a为负数,左端应补满1;如果a为无符号整数型,则左侧添满0。

本文来源:《C程序设计》谭浩强

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值