C语言中的位运算符和源码反码补码的浅解

发布时间 2023-04-10 18:22:03作者: 沉默的王さん

位运算符【与(&);或(|);非(~);异或(^);移位运算符(<< 和 >>)】

对于有符号(正负)的而言:

1)二进制的最高位是符号位:0表示正数,1表示负数
2)正数的原码,反码,补码都一样
3)负数的反码=它的原码符号位不变,其它位取反(0->1,1->0)
4)负数的补码=它的反码+1 
5) 

0在计算机种分+0与-0,它们的原码,补码,反码如下:

1、[+0]原码=0000 0000,   [-0]原码=1000 0000;

2、[+0]反码=0000 0000,   [-0]反码=1111 1111;

3、[+0]补码=0000 0000,   [-0]补码=0000 0000;

6)在计算机运算的时候,都是以补码的方式来运算的.(注意)

7)负数的源码-(除了左边第一位,也就是符号位不动,其它取反)>反码-(反码+1)>补码

 

1.与(&)运算符
规则:两个对应操作数的二进制位都为1结果位才为1,否则为0

例:
1 & 2
1为正数,所以源码反码补码都一样,2也是,计算机在运算时使用补码来运算,我们写出1和2的补码
1的补码:00000000 00000000 00000000 00000001
2的补码:
00000000 00000000 00000000 00000010

按照 & 规则逐位进行对比
1的补码:00000000 00000000 00000000 00000001
   &
2的补码:00000000 00000000 00000000 00000010         
 结果: 00000000 00000000 00000000 00000000 
+-0的补码是一样的,所以 1 & 2 = 0
--------------------------------------------------
下面使用负数举一个例子
-3 & -4
-3的
源码:10000000 00000000 00000000 00000011
反码(除了符号位不变,其余取反)
  :11111111 11111111 11111111 11111100
补码(反码+1)
  :11111111 11111111 11111111 11111101

同理我们写出-4的原码反码补码
-4的
源码:10000000 00000000 00000000 00000100
反码(除了符号位不变,其余取反)
  :11111111 11111111 11111111 11111011
补码(反码+1)
  :11111111 11111111 11111111 11111110
按照 & 规则逐位进行对比
-3的补码:11111111 11111111 11111111 11111101
  &
-4的补码:11111111 11111111 11111111 11111110
    结果:11111111 11111111 11111111 11111100 (该结果为补码)
补码 -(反码变补码+1,补码变反码当然是-1)>反码
补码:11111111 11111111 11111111 11111100 -(减1)>
反码:11111111 11111111 11111111 11111011 -(除符号位全部取反)>
原码:10000000 00000000 00000000 00000100=-4
所以 -3 & -4 = 4

下面的运算符变换原码反码补码的过程一样,不再举例说明

2.或(|)运算符
规则:两个对应操作数的二进制位都为0结果位才为0,否则为1

3.非(~,按位取反)运算符
规则:一个二进制操作数,对应位为0,结果位为1;对应位为1,结果位为0

4.异或(^)运算符
规则:两个操作数对应二进制位相同,则结果位为0,不同则为1

5.移位运算符(<< 和 >>)
1. 左移(<<)运算符

规则:二进制左移运算符,将一个运算对象的各二进制位全部左移若干位,左边的二进制位丢弃,右边补0

1. 右移(>>)运算符
规则:二进制右移运算符,将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

-3的
源码:10000000 00000000 00000000 00000011
反码:11111111 11111111 11111111 11111100
补码:11111111 11111111 11111111 11111101
左移举例
-3 << 4
-3的补码:11111111 11111111 11111111 11111101
左移4位
(舍弃)1111|1111 11111111 11111111 11111101|0000(补0)
整理一下:11111111 11111111 11111111 11010000
转为反码:11111111 11111111 11111111 11001111
转为原码:10000000 00000000 00000000 00110000
结果为:-48
右移举例
-3 >> 4
-3的补码:11111111 11111111 11111111 11111101
右移4位
(负数左边补1)1111|11111111 11111111 11111111 1111|1101(舍弃)
整理一下:11111111 11111111 11111111 11111111
转为反码:11111111 11111111 11111111 11111110
转为原码:10000000 00000000 00000000 00000001
结果为:-1

 

注:当运算数为正数,右移可以直接除以2^n

例:n=4   19 >> n = 19/2/2/2/2 =

19/2=9......1(遇到小数位丢弃)

9/2=4........1

4/2=2

2/2=1

所以19 >> 4 = 1

相反的,左移可以直接乘以2^n

例:n=4   1 << n = 1*2*2*2*2 = 

1*2=2

2*2=4

4*2=8

8*2=16

所以 1 << 4 = 16

如果是复数则需变成补码进行位移

end;