Bootstrap

C语言基础——位运算符*

运算符

术语

示例

结果

&

按位与运算

011 & 101

2个都为1才为1,结果为001

|

按位或运算

011 | 101

有1个为1就为1,结果为111

^

按位异或运算

011 ^ 101

不同的为1,结果为110

~

取反运算

~011

100

<<

左移运算

1010

10100

>>

右移运算

1010 >> 1

0101

ps:取反、左右位移运算需要在补码的基础上运算。 

1、按位与(&)

如果一个为0即为0,两个都为1时才为1

eg:40&15=8

        0010 1000    --->40

        0000 1111    --->15

-------------------------------

        0000 1000    --->8

2、按位或(|)

有1即为1,全0为0

eg:40|15=47

        0010 1000    --->40

        0000 1111    --->15

-------------------------------

        0010 1111    --->47

3、按位异或(^)

相同为0,不同为1

eg:40^15=39

        0010 1000    --->40

        0000 1111    --->15

-------------------------------

        0010 0111    --->39

4、按位取反(~)

对补码进行取反,再将取反后的补码转为原码

(1)正数取反:由于正数的原码、反码、补码相同,即三码合一。

        补码(原码) -> 取反(全反) -> 补码逆运算(-1) -> 反码逆运算(符号位不变) -> 原码 

eg:~40=0010 1000  ----原码(补码)

              =1101 0111  ----补码取反(全反)--补码

              =1101 0110  ----补码逆运算(-1)--反码

              =1010 1001  ----反码逆运算(取反,符号位不变)--原码

              =-41

(2)负数取反:原码 -> 反码 -> 补码 -> 取反 -> 补码(原码)

eg:~-15=1000 1111  ----原码

               =1111 0000  ----原码取反(符号位不变)--反码

               =1111 0001  ----反码+1  --补码

               =0000 1110  -----补码取反(全反)--补码(原码)

               =14

5、左移运算符(<<)

将二进制补码全部向左移动,空出来的位置补0,超出范围的二进制数丢弃

eg:40<<4=0010 1000<<4  --三码合一

                  =1000 0000(特殊情况,不需要逆运算)

                  =-128

有符号的数据左移后最高位如果为1,则需要进行逆运算

eg:41<<4=0010 1001<<4  ---三码合一

                  =1001 0000  ----左移四位  --补码

                  =1000 1111  ----补码-1  --反码

                  =1111 0000  ----反码取反(符号位不变)--原码

                  =-112

eg:-41<<4=1010 1001<<4  ---原码

                   =1101 0110  ----原码取反(符号位不变)  --反码

                   =1101 0111  ----反码+1  --补码 

                   =0111 0000  ---三码合一

                   =112

运算规则:在一定范围转内,数据每向左移动一位,相当于原数据*2 (正数、负数都适用)

6、右移运算符(>>)

逻辑移位:将数字的二进制补码全部向右移动,空出来的位置补0,超出范围的二进制数丢弃

eg:15 >> 4 = 0000 1111 >> 4

                     = 0000 0000

                     = 0

算术移位:左边移入的位由原先该值的符号位决定,符号位为1,则移入的位均为1,符号位为0,则移入的位均为0,这样能保证原数的正负形式不变

eg:-15 >> 2 = 1000 1111 >> 2   ---原码

                      = 1111 0000 >> 2   ---反码(注意:负数反码符号位不变)

                      = 1111 0001 >> 2   ---补码

                      = 1111 1100   ---补码(注意:算术右移左侧空出来的位置需要根据符号位来补位)

                      = 1111 1011   ---反码(补码转反码只需-1即可)

                      = 1000 0100 ----反码取反(符号位不变)   ---原码

                      = -4

标准规定:无符号值执行的所有位移操作都是逻辑移位,对于有符号值,到底采用逻辑移位还是算术移位取决于编译器。(一般为逻辑移位)

运算规则:在一定范转内,数据每向右移动一位,相当于原数据/2 (正负数都适用)

注意: 如果不能整除,向下取整

7、例题

(1)num=0x5678ffb3的8-15位取出来

        num=(num&(0x0000ff00))>>8

(2)num=0x5678ffb3的第2位值1,其余不变

        num|=1<<2

(3)num=0x5678ffb3的第1位值0,其余不变

        num^=1<<1

面试题

高效的方法计算2*8的值

        2<<3 或 8<<1

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。