一、补码,反码
正数的源码=反码=补码
负数的反码等于符号位不变,其余位按位取反
负数的补码等于反码+1
二、按位与,按位或,按位异或,按位非
1.按位与 &
0&0=0; 1&0=0; 1&1=1
任意二进制位与0都为0,与1为其本身 (a&0=0 ; a&1=a)
2.按位或 |
0|0=0; 0|1=1; 1|1=1
任意二进制位或1都为1,或0为其本身 (a|0=a ; a|1=1)
3.按位异或 ^
两个二进制位相同为0,不同为1
0^0=0 ; 0^1=1; 1^1=0
4.按位非 ~
所有位按位取反(区别于反码的符号位不变)
注意:按位非后的二进制串为补码,读取时要化为原码
int main() {
int a = 0; //补码:00000000 00000000 00000000 00000000
int b = ~a; //补码:11111111 11111111 11111111 11111111 反码:11111111 11111111 11111111 11111110 原码:10000000 00000000 00000000 00000001
printf("%d", b); // 结果为-1
return 0;
}
int main() {
int a = -2; //原码:10000000 00000000 00000000 00000010 反码:11111111 11111111 11111111 11111101 补码:11111111 11111111 11111111 11111110
int b = ~a; //补码:00000000 00000000 00000000 00000001
printf("%d", b); //结果为1
return 0;
}
三、左移,右移
1.左移
将补码的二进制位左移,左端舍弃,右端补0
a左移n位代表,a=a*2^n
int main() {
int a = -2; //原码:10000000 00000000 00000000 00000010 反码:11111111 11111111 11111111 11111101 补码:11111111 11111111 11111111 11111110
int b = a<<1; //补码:11111111 11111111 11111111 11111100 反码:11111111 11111111 11111111 11111011 原码:10000000 00000000 00000000 00000100
printf("%d", b); //结果为-4
return 0;
}
2.右移
将补码的二进制位右移,右端舍弃,左端补0或符号位(无符号类型补0,有符号类型补符号位)
a右移n位代表,a=a/2^n
int main() {
int a = -2; //原码:10000000 00000000 00000000 00000010 反码:11111111 11111111 11111111 11111101 补码:11111111 11111111 11111111 11111110
int b = a>>1; //补码:11111111 11111111 11111111 11111111 反码:11111111 11111111 11111111 11111110 原码:10000000 00000000 00000000 00000001
printf("%d", b); //结果为-1
return 0;
}