位运算操作符、位操作符详解

一、二进制位

想要弄明白位运算操作符、逻辑操作符,首先要知道整型在计算机内存中的存储方式
注:移位操作符、位操作符针对的必须是整型数据

我们较为熟悉的是十进制,可以用十进制类比二进制
十进制中数字的范围是0~9,不会出现10,同理,二进制只有数字0和1,没有2及以上的数字
下面用111这个数字来举例
如果这是一个十进制数字,那么它的大小是1 * 10 ^ 2 + 1 * 10 ^ 1 + 1 * 10 ^ 0 = 111
如果这是一个二进制数字,那么它的大小是1 * 2 ^ 2 + 1 * 2 ^ 1 + 1 * 2 ^ 0 = 7
也就是说,一个n进制的数字,如果第m位上的数字是p,那么这一位表示的大小是p * n ^ (m - 1)

下面介绍整型数据的原码、反码、补码,由原码得到补码的基本运算规则就是:
原码符号位不变,其他位按位取反得反码;反码+1得补码
反过来,由补码得到原码:
补码-1得反码;反码符号位不变,其他位按位取反得原码

对于一个数字,我们可以很轻松的写出它的原码,经过上面的运算得到它的补码后,便可进行位运算操作和逻辑操作

注1:移位操作和位操作针对的都是数据的补码
注2:正整数在内存中的原码、反码和补码相同,存储时最高位(即符号位)是0
注3:负整数的补码则需通过上面的运算规则计算得出,存储时最高位(即符号位)是1

二、移位操作符

1.左移操作符 <<

左移操作符:左边丢弃,右边补0(相当于对这个数字乘2)

代码如下(示例):

int main()
{
	int a = 5;
	//00000000 00000000 00000000 00000101   5的原码、反码、补码
	//内存中存的是补码
	int b = a << 1;
	//00000000 00000000 00000000 00001010	b的原码、反码、补码
	printf("b = %d\n", b);//b = 10
}

由于a是正数,所以a的原码、反码和补码都相同,为
00000000 00000000 00000000 00000101
左移操作符规则是左边丢弃,右边补0,所以运算后b的原码、反码和补码为
00000000 00000000 00000000 00001010
转化为10进制就是10

2.右移操作符 >>

右移操作符的运算规则与左移操作符类似:右边丢弃,左边补0或1
但是由于左边最高位涉及到符号的问题(0表示正数,1表示负数),所以右移操作分为逻辑右移和算术右移

(1)算术右移

运算规则:左边补原来的符号位,右边丢弃。

代码如下,具体的运算细节已用注释写出:

int main()
{
	int a = 5;
	int b = a >> 1;
	//00000000 00000000 00000000 00000101   5的原码、反码、补码
	//00000000 00000000 00000000 00000010	b的原码、反码、补码
	printf("b = %d\n", b);//b = 2

	a = -5;
	int c = a >> 1;
	//10000000 00000000 00000000 00000101	-5的原码
	//11111111 11111111 11111111 11111010	-5的反码
	//11111111 11111111 11111111 11111011	-5的补码

	//11111111 11111111 11111111 11111101   c的补码
	//11111111 11111111 11111111 11111100	c的反码
	//10000000 00000000 00000000 00000011   c的原码
	printf("c = %d\n", c);//c = -3
	//说明当前编译器(VS2013)默认是算术右移
	return 0;
}

(2)逻辑右移

与算数右移同理,只需在移位后最高位补0即可,此处不再赘述。

二、位操作符

首先要明确位操作符中的“位”是指二进制数的补码的比特位

1.按位与&

按位与的运算规则:二进制位中有0就是0,全1才为1
代码如下,具体的运算细节已用注释写出:

int main()
{
	int a = -1;
	int b = -2;
	int c = a & b;
	//10000000 00000000 00000000 00000001	a原码
	//10000000 00000000 00000000 00000010	b原码
	//按位与
	//10000000 00000000 00000000 00000000	
	//用原码计算是错误的
	//c的结果应该是-2,很显然逻辑运算用的是补码而不是原码
	printf("%d\n", c); //-2
	//11111111 11111111 11111111 11111111	a补码
	//11111111 11111111 11111111 11111110	b补码
	//按位与
	//11111111 11111111 11111111 11111110	-2
}

2.按位或 |

按位或的运算规则:二进制位中有1就是1,全0才为0
代码如下,具体的运算细节已用注释写出(方便起见,用正数运算):

int main()
{
	int a = 5;
	int b = 3;
	//00000000 00000000 00000000 00000101	a
	//00000000 00000000 00000000 00000011	b
	//按位或
	//00000000 00000000 00000000 00000111	c
	int c = a | b;
	printf("%d\n", c);//c = 7
}

3.按位异或 ^

按位异或的运算规则:二进制位相同为0,相异为1
代码如下,具体的运算细节已用注释写出:

int main()
{
	int a = 5;
	int b = 3;
	//00000000 00000000 00000000 00000101	a
	//00000000 00000000 00000000 00000011	b
	//00000000 00000000 00000000 00000110	c
	int c = a ^ b;
	printf("%d\n", c);//c = 6
}

感谢阅读,如有错误请批评指正

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值