原码,反码,补码及其相关操作符

在计算机中,我们使用补码来进行表示和存储。什么是补码呢?

要了解补码,首先我们要先了解原码,反码。原码很简单,就是该数字的2进制表示,在32位计算机上占32个bit位,其余类似(下面统一用32位),其中最高位表示符号位,1表示负数,0表示正数。比如1的原码就是0000 0000 0000 0000 0000 0000 0000 0001,2的原码是0000 0000 0000 0000 0000 0000 0000 0010。-1的原码是1000 0000 0000 0000 0000 0000 0000 0001。正数和负数的反码求法不同,其中正数的反码与原码相同,而负数的反码是原码除最高位符号位不变,其他按位取反。比如-1的反码就是1111 1111 1111 1111 1111 1111 1111 1110.。正数的补码也还是与原码相同,而负数的补码则是其反码加1。比如-1的补码就是1111 1111 1111 1111 1111 1111 1111 1111。总的来看,正数的原码,反码,补码相同。负数的反码是原码除最高位取反,补码是反码加1。

在计算机中,我们的加减都是通过补码来计算的。举个例子,1-1=0这个式子在计算机中会转换成1+(-1)。其中1的补码是0000 0000 0000 0000 0000 0000 0000 0001,-1的补码是1111 1111 1111 1111 1111 1111 1111 1111。补码一加就是1 0000 0000 0000 0000 0000 0000 0000 0000。但我们是32位下,所以第33位上的1是不算的,最后得出的是0000 0000 0000 0000 0000 0000 0000 0000,也就是0。其余的加减也类似。

在c语言中,我们有许多操作符用来操作补码的。

首先,移位操作符<<和>>。左移操作符<<是左边抛弃,右边补0。比如-1的补码是1111 1111 1111 1111 1111 1111 1111 1111,我们左移两位就变成了1111 1111 1111 1111 1111 1111 1111 1100。这个数转换为原码就是1000 0000 0000 0000 0000 0000 0000 0100,也就是-4。通过vs运行一下

#include <stdio.h>
int main()
{
	int a = -1;
	a=a << 2;
	printf("%d", a);
	return 0;
}

运行结果就是-4。而右移操作符有两种运行方式。一种与左移操作符类似,就是右边抛弃,左边补0,另外一种就是左边用原来的值来填充,右边抛弃。其中,我们普遍认为第一种比较暴力,所以大多数编译器不支持,也就是说我们平常使用的编译器都是用第二种做法的。举个例子。-2的补码是1111 1111 1111 1111 1111 1111 1111 1110。右移两位就是1111 1111 1111 1111 1111 1111 1111 1111,也就是-1的补码。运行结果也是-1。说明vs是支持第二中做法的。

#include <stdio.h>
int main()
{
	int a = -2;
	a=a >> 2;
	printf("%d", a);
	return 0;
}

其次c语言还支持位操作符,比如按位与&,按位或|,按位异或^,按位取反~。按位或&的执行就是两个数中,补码中相同位上只要有0就是0,两个同时为1才为一。别入1和-1,1的补码是0000 0000 0000 0000 0000 0000 0000 0001,-1的补码是1111 1111 1111 1111 1111 1111 1111 1111,最后结果是0000 0000 0000 0000 0000 0000 0000 0001,也就是1。vs上运行结果如图。           

#include <stdio.h>
int main()
{
	int a = 0;
	a=1&-1;
	printf("%d", a);
	return 0;
}

按位或|,一听名字就知道与&相反。|执行的两个数中,只要有1就是1,两个同时为0才为0。同样是1和-1。1的补码是0000 0000 0000 0000 0000 0000 0000 0001,-1的补码是1111 1111 1111 1111 1111 1111 1111 1111,最后结果是1111 1111 1111 1111 1111 1111 1111 1111,也就是-1。vs上运行结果如图

#include <stdio.h>
int main()
{
	int a = 0;
	a=1|-1;
	printf("%d", a);
	return 0;
}

按位异或^,表示两个数中相同为0,相异为1。以1和-1为例1的补码是0000 0000 0000 0000 0000 0000 0000 0001,-1的补码是1111 1111 1111 1111 1111 1111 1111 1111,结果为1111 1111 1111 1111 1111 1111 1111 1110,也就是-2。VS上运行结果如图。

#include <stdio.h>
int main()
{
	int a = 0;
	a=1^-1;
	printf("%d", a);
	return 0;
}

按位取反~,如其名,就是补码全部取反。比如1 ,补码是0000 0000 0000 0000 0000 0000 0000 0001,取反后1111 1111 1111 1111 1111 1111 1111 1110,也就是-2。VS上运行结果如图。

#include <stdio.h>
int main()
{
	int a = 0;
	a=~1;
	printf("%d", a);
	return 0;
}

学完这些,我们来做一下一个题目,如何在不创建变量的情况下交换两个值。我们要用的就是按位异或^,我们首先要理解一个事情,就是任意数a^a=0,而任意数b^0=b。所以a=a^b,b=a^b,a=a^b。我们把原a值赋为1,b赋为-1。第一个a^b就是1^-1,第二个a^b就是1^-1^-1,就等于1,第三个a^b就是1^-1^1.等于-1。结果如图。

#include <stdio.h>
int main()
{
	int a = 1;
	int b = -1;
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d b=%d", a,b);
	return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值