移位运算符的效果

移位运算符介绍

以C语言为例,在C语言中移位运算符是指将二进制位向左或者向右移动n位,其操作数必须为整型。左移运算符:<< ;右移运算符:>>

一、左移运算符

1.1左移运算规则

左移运算符将运算对象每一位二进制的值向左移动指定的位数,左末端的值丢失,右侧补0。
例如:-5用二进制表示为
10000000 00000000 00000000 00000101(原码)
11111111 11111111 11111111 11111011 (补码)
左移1位后等于-10:
11111111 11111111 11111111 11110110(补码)
10000000 00000000 00000000 00001010(原码)

1.2左移的运算效果

首先我们看一段代码:

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

程序最后运行的结果为:在这里插入图片描述
我们可以看到,左移移位后,相当于在原来的基础上乘2,这是巧合么还是必然呢?

对于正数而言,转换成二进制后,第n位的权重为 2^ (n-1), 当左移一位后,原本的第n位到了n+1位,权重变成了 2^n,所以左移一位相当于乘2。对于负数,同样的道理,左移一位也相当于乘2。哪怕是超过了整型范围,其结果也相当于乘2。
例如:

#include<stdio.h>
int main()
{
	int a = 1073741825;
	int c = 2 * a;
	int b = a << 1;
	printf("%d\n", b);
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

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

在这里插入图片描述

二、右移运算符

2.1右移运算规则

右移1位,将当前操作数的所有二进制位向右移动一位。对于无符号类型,左侧补0;对于有符号类型,其结果取决于机器。左侧可以补0,也可以补1。(算数右移左侧补符号位,逻辑右移左侧补0)VS2019中遵循算数右移规则,因此我们对算数右移进行分析。

例如:5用二进制表示为
00000000 00000000 00000000 00000101
左移1位后等于2:
00000000 00000000 00000000 00000010
-5用二进制表示为
10000000 00000000 00000000 00000101(原码)
11111111 11111111 11111111 11111011 (补码)
左移1位后等于-3:
11111111 11111111 11111111 11111101(补码)
10000000 00000000 00000000 00000011(原码)

2.2 右移的运算效果

正数

右移1位原本第n位将被移到第n-1位,权重将会由2^(n-1)变为 2^(n-2),因此相当于除以2

负数

当N为奇数时:
符号位为1,最低为也为1
1××××××× ×××××××× ×××××××× ×××××××1(原码)
1******* ******** ******** *******1(补码)
其中 * 表示×取反后的结果
右移1位后变成
11 ****** ******** ******** ********(补码)
10×××××× ×××××××× ×××××××× ×××××××(×+1)(原码)
将原码换种方式表示
10×××××× ×××××××× ×××××××× ×××××××× +1
由于符号位是负,因此在最后一位上加上1,相当于加上
10000000 00000000 00000000 00000001(即-1)因此相当于将原来的数减去1,可以看见,在减1之前,相当于原来的原码,每一位的权重变为了原来的1/2,因此当N为基数时,右移1位相当于除以2再减1,即N=N/2-1。
因为N为基数,所以 N/2 - 1 =(N-1) /2。

当N为偶数时,符号位为1,最低为为0
1××××××× ×××××××× ×××××××× ×××××××0(原码)
1******* ******** ******** ******* 1(反码)
1******* ******** ******** ******( *+1)0(补码) 最后1位1加上1会向高位进1,我们表示为 *+1
当N向右移动1位后变成

11****** ******** ******** ******( *+1) (补码)
10×××××× ×××××××× ×××××××× ××××××××(原码)
这里由补码求原码的时候,我们用原码=(补码-1)取反,就可以把( *+1)的1处理掉,从而得到
10×××××× ×××××××× ×××××××× ××××××××,和移位前相比,每位的权重变为了原来的1/2,因此N为偶数时,右移1位,相当于除以2,即N=N/2。
因为N为偶数,所以N/2 = (N-1)/2。
当操作数为负时,左移一位相当于(N-1)/2。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值