左移右移置位

int i = 1;
i = i << 2;  //把i里的值左移2位

也就是说,1的2进制是000...0001(这里1前面0的个数和int的位数有关,32位机器,gcc里有31个0),左移2位之后变成 000...0100,也就是10进制的4,所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因)

int i = 0x40000000; //16进制的40000000,为2进制的01000000...0000
i = i << 1;

那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000...0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出.如果再接着把i左移1位会出现什么情况呢?在C语言中采用了丢弃最高位的处理方法,丢弃了1之后,i的值变成了0.

总之左移就是: 丢弃最高位,0补最低位

右移对符号位的处理和左移不同,对于有符号整数来说,比如int类型,右移会保持符号位不变,例如:

int i = 0x80000000;
i = i >> 1;  //i的值不会变成0x40000000,而会变成0xc0000000

就是说,符号位向右移动后,正数的话补0,负数补1,也就是汇编语言中的算术右移.同样当移动的位数超过类型的长度时,会取余数,然后移动余数个位.

负数10100110 >>5(假设字长为8位),则得到的是  11111101

总之,在C中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变.实际应用中可以根据情况用左/右移做快速的乘/除运算,这样会比循环效率高很多.

左移操作(<<)
规则:
右边空出的位用0填补
高位左移溢出则舍弃该高位。
计算机中常用补码表示数据:
数据 127,补码和原码一样:0111 1111。
左移一位: 1111 1110   -> 这个补码对应的原码为:1000 0010  对应十进制:-2
左移二位: 1111 1100   -> 这个补码对应的原码为:1000 0100  对应十进制:-4
左移三位: 1111 1000   -> 这个补码对应的原码为:1000 1000  对应十进制:-8
左移四位: 1111 0000   -> 这个补码对应的原码为:1001 0000  对应十进制:-16
左移五位: 1110 0000   -> 这个补码对应的原码为:1010 0000  对应十进制:-32
左移六位: 1100 0000   -> 这个补码对应的原码为:1100 0000  对应十进制:-64
左移七位: 1000 0000   -> 这个补码对应的原码为:1000 0000  对应十进制:-128
左移八位: 0000 0000   -> 这个补码对应的原码为:0000 0000  对应十进制:0
注:
原码到补码的计算方式:取反+1,正数的补码和反码等于源码(化为二进制后高位补0符号位)
补码到原码的计算方式:-1再取反。(求反码:符号位不变,数值取反;求补码:符号位不变,反码最低位加1,1+1=0进1)
数据-1,它的原码为1000 0001,补码为1111 1111
左移一位: 1111 1110   -> 这个补码对应的原码为:1000 0010  对应十进制:-2
左移二位: 1111 1100   -> 这个补码对应的原码为:1000 0100  对应十进制:-4
左移三位: 1111 1000   -> 这个补码对应的原码为:1000 1000  对应十进制:-8
左移四位: 1111 0000   -> 这个补码对应的原码为:1001 0000  对应十进制:-16
左移五位: 1110 0000   -> 这个补码对应的原码为:1010 0000  对应十进制:-32
左移六位: 1100 0000   -> 这个补码对应的原码为:1100 0000  对应十进制:-64
左移七位: 1000 0000   -> 这个补码对应的原码为:1000 0000  对应十进制:-128
左移八位: 0000 0000   -> 这个补码对应的原码为:0000 0000  对应十进制:0
可以看出127和-1的结果完全一样。移位操作与正负数无关,它只是忠实的将所有位进行移动,补0,舍弃操作。
右移操作(>>)
规则:
左边空出的位用0或者1填补。正数用0填补,负数用1填补。注:不同的环境填补方式可能不同;

低位右移溢出则舍弃该位。

1、127的补码:0111 1111

右移一位: 0011 1111   -> 原码同补码一样  对应十进制:63

右移二位: 0001 1111   -> 原码同补码一样  对应十进制:31

右移三位: 0000 1111   -> 原码同补码一样  对应十进制:15

右移四位: 0000 0111   -> 原码同补码一样  对应十进制:7

右移五位: 0000 0011   -> 原码同补码一样  对应十进制:3

右移六位: 0000 0001   -> 原码同补码一样  对应十进制:1

右移七位: 0000 0000   -> 原码同补码一样  对应十进制:0

右移八位: 0000 0000   -> 原码同补码一样  对应十进制:0

2、-128的补码:1000 0000

右移一位: 1100 0000   -> 这个补码对应的原码为:1100 0000  对应十进制:-64

右移二位: 1110 0000   -> 这个补码对应的原码为:1010 0000  对应十进制:-32

右移三位: 1111 0000   -> 这个补码对应的原码为:1001 0000  对应十进制:-16

右移四位: 1111 1000   -> 这个补码对应的原码为:1000 1000  对应十进制:-8

右移五位: 1111 1100   -> 这个补码对应的原码为:1000 0100  对应十进制:-4

右移六位: 1111 1110   -> 这个补码对应的原码为:1000 0010  对应十进制:-2

右移七位: 1111 1111   -> 这个补码对应的原码为:1000 0001  对应十进制:-1

右移八位: 1111 1111   -> 这个补码对应的原码为:1000 0001  对应十进制:-1

常见应用
左移相当于*2,只是要注意边界问题。如char a = 65; a<<1 按照*2来算为130;但有符号char的取值范围-128~127,已经越界,多超出了3个数值,所以从-128算起的第三个数值-126才是a<<1的正确结果。
而右移相当于除以2,只是要注意移位比较多的时候结果会趋近去一个非常小的数,如上面结果中的-1,0。
其它的四种位运算:
与运算(&)
1、与0相与可清零
2、与1相与可保留原值
或运算(|)
1、与0相或可保留原值
2、与1相与可齐设1
异或运算(^)
1、与0异或保留原值
2、与1异或比特值反转
3、可通过某种算法,使用异或实现交换两个值
异或运算是有结合律的
取反(~)

来源:https://www.cnblogs.com/yyangblog/archive/2011/01/14/1935656.html

时间: 2024-08-10 06:45:55

左移右移置位的相关文章

关于 C/C++左移右移运算符 的总结

一.概述 本文是根据整合网上资料与相关博文总结出来的关于[ C/C++左移右移运算符 ]的知识. 二.正文 (1)结合图示篇,更加简单明了. 移位运算包含“逻辑移位”(logical shift)和“算术移位”(arithmetic shift). 逻辑移位:移出去的位丢弃,空缺位(vacant bit)用 0 填充. 算术移位:移出去的位丢弃,空缺位(vacant bit)用“符号位”来填充,所以一般用在右移运算中. c++中,整数分有符号数和无符号数两种,对于这两种数做左移.右移运算,稍有区

jQuery实现左移右移

1 <html> 2 <head> 3 <meta charset="utf-8"> 4 <title>完成左移右移</title> 5 <script src="jquery.js"></script> 6 <style type="text/css"> 7 table{background-color:purple;} 8 input{backgr

EASYUI- EASYUI左移右移 GRID中值

EASYUI左移右移 GRID中值 $("#addAll").click(function(){ var ids = []; var names = []; var srcrows = $('#sourceTable').datagrid('getSelections'); if(srcrows.length == 0 ){ Sys.InfoShow("请选择要移动的记录!"); return; } var id;var name; for(var srci=src

嵌入式C开发---用循环实现左移右移

//将n左移m位 int byte_to_left_move(int n , int m) { int i , ret = 1 ; if(n == 0 || n < 0) { return ; } if(n == 1) { for(i = 0 ; i < m ; i++) ret *= n * 2 ; } if(n > 1) { for(i = 0 ; i < m ; i++) ret *= n ; } return ret ; } //将n右移m位 int byte_to_rig

【C#】关于左移/右移运算符的使用

吐槽先~为什么我的老师大学时候没教过我这东西  - -. 继续送栗子: 比如 “(1+2)<<3” 你们猜等于几~ Debug.Log((1+2)<<3)之后输出的是“24”. 为什么呢~ 因为呀因为呀  “ “左移/右移” 是指对应的二进制向左右移位,执行1+2=3,就变成了3<<3.即:把3对应的二进制向左移3位. 3对应的二进制:11   向左移3位变成 11000 二进制11000不就是十进制的24嘛~~~” 继续拓展一下思维 3>>1<<

左移右移(转)

先说左移,左移就是把一个数的所有位都向左移动若干位,在C中用<<运算符.例如: int i = 1;i = i << 2;  //把i里的值左移2位需要注意的一个问题是int类型最左端的符号位和移位移出去的情况.我们知道,int是有符号的整形数,最左端的1位是符号位,即0正1负,那么移位的时候就会出现溢出,例如: int i = 0x40000000; //16进制的40000000,为2进制的01000000...0000i = i << 1; 那么,i在左移1位之后

easyUI 两个grid表格数据左移右移代码

做项目中经常遇到选择已有数据,移动到选择好数据grid的场景,比如为项目添加员工,左侧grid是待选择员工,选好后移动到右侧grid,这里我用的jquery-easyui-1.4.2,整理出一份grid数据移动的代码,可以直接使用. 1.jsp代码:(创建两个easyui-datagrid,左右横向排列) <table>     <tr><td><table id="leftGrid" class="easyui-datagrid&q

位操作——高低位交换(循环左移/右移)

给出一个16位的无符号整数.称这个二进制数的前8位为“高位”,后8位为“低位”.现在写一程序将它的高低位交换.例如,数34520用二进制表示为: 10000110 11011000 将它的高低位进行交换,我们得到了一个新的二进制数: 11011000 10000110 它即是十进制的55430. 这个问题用位操作解决起来非常方便,设x=34520=10000110 11011000(二进制) 由于x为无符号数,右移时会执行逻辑右移即高位补0,因此x右移8位将得到0000000010000110.

友元函数实现操作符重载的应用场景-友元函数实现左移右移操作符重载

先定义一个测试类Complex,其中用成员函数的方法重载了+.-.前置++.前置--.后置++.后置--这6个运算符,当然,这6个操作符也可以用友元函数方式重载,但习惯上这些都直接用成员函数方式重载. demo #include <iostream> using namespace std; class Complex { public: Complex(int a = 0, int b = 0) { this->a = a; this->b = b; } ~Complex();