版权声明:本文为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);
}