计算机运算都是基于补码进行运算的。
我们就不得不了解一下原码、反码、补码
正整数部分:
(1)原码、反码和补码都一样
负整数部分:
(1)原码和反码的相互转换:符号位不变,数值位按位取反
(2)原码和补码的相互转换:符号位不变,数值位按位取反,末位再加1
位运算符
原码转补码,补码运算,补码转原码。
因为正整数原码、反码和补码都一样(直接用原码运算),所以用负数当例子
1、按位与(&):同 1 为 1,有 0 为 0
例子:10001001(-9)与10001111(-15)得10001111(-15)
2、按位或(|):有 1 为 1,同 0 为 0
例子:10001001(-9)或10001111(-15)得10001001(-9)
3、取反运算(~):取反(符号位也改变)
例子:10001001(-9)取反得00001000(8)
4、异或:同为 0,不同为 1
例子:10001001(-9)异或10001111(-15)得00000110(6)
5、同或(C没提供,但是异或取反就是同或)
验证代码
#include<stdio.h>
int main(){
int x=-9;
int y=-15;
int a,b,c,d;
a=x&y;
printf("与运算:%d\n",a);
b=x|y;
printf("或运算:%d\n",b);
c=~x;
printf("取反预算:%d\n",c);
d=x^y;
printf("异或运算:%d\n",d);
return 0;
}
移位运算包含“逻辑移位”(logical shift)和“算术移位”(arithmetic shift)。
逻辑移位:移出去的位丢弃,空缺位(vacant bit)用 0 填充。
算术移位:移出去的位丢弃,空缺位(vacant bit)用“符号位”来填充,所以一般用在右移运算中。
1、如果是无符号数,不管是左移还是右移都是“逻辑移位” (空缺位用0填充)
2、如果是有符号数
- 如果是做左移运算,那么做的是“逻辑移位”(后面用0填充)
- 如果是做右移运算,那么做的是“算术移位”(前面用1填充)
以10001001(-9)为例
-9>>1 -9<<1
原码:10001001
补码:11110111
移位:11110111>>1 11110111<<1
补码:11111011 11101110
原码:10000101(-5) 10010010(-18)
验证代码
#include<stdio.h>
int main(){
int a,b,c;
a=-9;
printf("%d\n",a);
printf("\n");
b=a;
c=a;
for(int i=0;i<10;i++){
b=b>>1;
printf("%d\n",b);
}
printf("\n");
for(int j=0;j<10;j++){
c=c<<1;
printf("%d\n",c);
}
return 0;
}