谈谈C语言中的位运算的一些事

版权声明:本文为CSDN博主「雷人小猪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zxh_2954588290/article/details/106183899

最近,我忽然之间发现C语言中说到的位运算有了些许的生疏,所以我就在这里写下关于位运算的文章,希望能够给自己加深理解和记忆,同时也希望能够帮助到小伙伴们。附上我喜欢的一句话:

纸上得来终觉浅,绝知此事要躬行。

导言

C语言中说的位运算其实就是进行比特位运算的意思,换种说法就是转换成为二进制再来运算。
而在C语言中有六种位运算符:

  •  运算符     说明
    
  •  <<        左移
    
  •  >>        右移
    
  •  ~         取反
    
  •  ^       按位异或
    
  •  |        按位或
    
  • &         按位与
    

下面我就来说一下这六种运算符的具体运算栗子。

左移(<<)

其实就是二进制位往左移动若干位,后面补零。
比如 6 << 2就是

6 -> 0000 0110
6 << 2 -> 0001 1000

我们就看到了,这时候 6 左移了两位之后变成了24,相当于乘上了22 。于是我们就不难知道其实这里有个小技巧就是:左移了n位其实就是相当于乘上了2n 。
那下面右移就会简单很多了。

右移(>>)

相对于左移来说,就是二进制位往右移动若干位溢出的就舍去,前面补零或一(看最高位来定)。
比如 6 >> 2 就是

6 -> 0000 0110
6 >> 2 -> 0000 0001
补充:
- 6 ->1111 1010
(- 6) >> 2 -> 1111 1110

我们也知道了,右移了两位之后,十进制的6变成了1,其实和上面相对就是:每右移一位就是相当于每除以一次 2。要注意的是, 这里的6/4==1,就像整型运算一样可以优化除法运算 ,还有就是负数由于要反码、补码可能会出现不一样的结果(就像我补充的 - 6 右移两位之后变成了 - 2)。

取反(~)(NOT)

这个听起来就感觉挺容易懂的。就是反过来的意思,对应的就是~ 0=1,~ 1=0。
比如~6:

6 -> 0000 0110
~6 ->1111 1001
补充:
- 6 ->1111 1010
~(- 6)-> 0000 0101

然后就可以的看到了 6 取反之后变成了 - 7 ,- 6 取反变成了 5 。我感觉我看到了 一个小技巧:取反带来了 ± 的改变,同时还有变成正的负的之后都要 -1 就变成了取反后的样子 。 这个和逻辑运算符 非(!)有点相似。
还可以判断是否输入为0(while(~scanf("%d",&n )))?

按位异或(^)(XOR)

简单来说,就是不同为1,同为0 (0^1=1 , 0^0 =0 , 1^1=0)。
就好比 6 ^12

6 -> 0000 0110
12 -> 0000 1100
6 ^ 12 -> 0000 1010

然后就有了6 ^ 12 等于10的结果。性质有:交换律,结合律( (a^ b)^ c == a^ (b^c)) ,还有
a ^a =0和a ^ 0 = a 。负数的按位异或也是同样的道理。

按位或(|)(OR)

这个就是类似于数学中的或,只要有真就是真,也就是说有1就是1,只有0或0才等于0(0 | 0=0)。
拿6 | 12来说就是

6 -> 0000 0110
12 -> 0000 1100
6 | 12 ->0000 1110

6 | 12变成了14,按位或运算可以用于二进制特定位置的赋值。负数同理。要注意的是这个按位或运算符和逻辑运算符 或( || )也有点相似的地方。

按位与(&)(AND)

只有两个都是位都是1结果才是1 (1&1=1),否则就是0。
还拿 6 & 12来说

6 -> 0000 0110
12 -> 0000 1100
6 & 12 ->0000 0100

此时6 & 12 就是4了。可以用于取二进制的指定位,清零,还有就是判断奇偶(就是看最后一位是0还是1)。这个也和逻辑运算符 与 (&&)类似。

优先级

位运算的优先级如下:

按位反(~)>位移运算(<<,>>)>按位与(&)>按位异或(^)>按位或(|)

还有复合型的位运算,只用用上正确的运算规则就可以了。

最后,送上验证的代码:

#include <stdio.h>
int main()
{
  int c,d,e,f,g;
  int a=6,b=12 ;
  c=a&b ;
  d=a|b ;
  e=a^b;
  f=~a;
  g=~(-a);
  printf("%d & %d=%d\n", a,b,c);
  printf("%d | %d=%d\n", a,b,d);
  printf("%d ^ %d=%d\n", a,b,e);
  printf("%d>>2=%d,%d<<2=%d,-%d>>2=%d\n",a, a>>2,a,a<<2,a,(-a)>>2);
  printf("~%d=%d,~(-%d)=%d\n",a,f,a,g);
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容