文章目录
正数的原反补相同,负数需要经过计算(减一取反)对于有符号数,二进制最高位为符号位
最高位为 0 ,是正数
最高位为 1 ,是负数
原码:直接按数字的正负转换为二进制是原码
反码:原码的符号位不变,其他位按位取反
补码:反码加一,符号位不变。
补码变回原码也可以取反加1,或者减1取反
补码方便负数计算
“%d”有符号数
“%u”无符号数
1)~ 按位取反(符号位改变)
int a=0;
//a的补码00000000 00000000 00000000 00000000
int b=~a;
//a取反后的补码(符号位也取反)11111111 111111111 111111111 111111111
//此时符号位为1,代表负数,需要计算得到原码
//减1得到反码11111111 11111111 11111111 11111110
//取反得到原码(符号位不变)10000000 000000000 000000000 000000001
printf("%d",b);//打印-1
2)左移操作符<<和右移操作符>>
移动的是存储在二进制中的补码
左移 ’ << ’
左边丢弃,右边补0
右移 ’ >> ’
1.逻辑右移 右边丢弃,左边补0
2.算数右移 右边丢弃,左边原符号补齐绝大部分为算数右移
int a=1;
int b=<<a;//a不变,b等于2
2.1)左移<<的实际运用
int a=13;
//1101变成1111;把0用1补上
//按位或(|)上0010
//1<<1(1左移1)就是0010
int b =a|(1<<1);
//在把b(1111)变回a(1101)
//按位与(&)上1101
//完整应该为11111111 11111111 11111111 11111101
//上式可以用取反~(1<<1)
int c=b&(~(1<<1))
3)&(按位与)
a=3
b=-2
c=a & b
&(按位与)全1为1
-2的原码10000000 00000000 00000000 00000010
反码11111111 11111111 11111111 11111101
补码11111111 11111111 11111111 11111110
3的补码00000000 00000000 00000000 00000011
a&b 补码00000000 00000000 00000000 00000010 (正数的原反补码一样)
结果 2
判断的是内存中的补码(负数的补码)
&1可以知道二进制最低一位是0/1
a=a>>1 & 1循环,每一位都判断一下,可以统计有几个1
//计算二进制中1的个数
int count_one_bit(unsigned int n)
{
int count = 0;
int i = 0;
for(i=0; i<32; i++)
{
if(((n>>i)&1) == 1)
count++;
}
return count;
}
4)| (按位或)
a=3
b=-2
c=a | b
|(按位或)
-2的补码11111111 11111111 11111111 11111110
3的补码00000000 00000000 00000000 00000011
a|b补码 11111111 11111111 11111111 11111111(负数计算)
反码11111111 11111111 11111111 11111110
原码10000000 00000000 00000000 00000001
结果是(-1)
5)^ (异或)
a=3
b=-2
c=a ^ b
^(异或)相同为0,相异为1
-2的补码11111111 11111111 11111111 11111110
3的补码00000000 00000000 00000000 00000011
a^b补码11111111 11111111 11111111 11111101
(负数)
反码11111111 11111111 11111111 11111100
原码10000000 00000000 00000000 00000011
结果(-3)
5.1)基于异或(^)的交换两个数(只适用于整型)
a = 3;//011
b = 5;//101
a = a ^ b;
//011^101=110
b = a ^ b;
//110^101=011
a = a ^ b;
//110^011=101
a^a=0
0^a=a
a^a^b=b
a^b^a=b
异或支持交换律