算术移位逻辑移位

unsigned int i = 8;
int main()
{
     i = i<<3;//输出结果i = 64
}

请问:上面的变量i是采用逻辑移位还是算术移位呢?

逻辑移位,简单理解就是物理上按位进行的左右移动,两头用0进行补充,不关心数值的符号问题。

算术移位,同样也是物理上按位进行的左右移动,两头用0进行补充,但必须确保符号位不改变。

  • 逻辑移位

逻辑移位是指逻辑左移和逻辑右移,移出的空位都用0来补。

此组指令有:逻辑左移SHL(ShiftLogical Left)和逻辑右移SHR(ShiftLogical Right)。它们的指令格式如下:SHL/SHR Reg/Mem, CL/Imm,受影响的标志位:CF、OF、PF、SF和ZF(AF无定义)。逻辑左移/右移指令只有它们的移位方向不同,移位后空出的位都补0

(1)逻辑左移SHL


(2)逻辑右移SHR

  • 算术移位

算术移位 就需要分有符号型值和无符号型值
==对于无符号型值,算术移位等同于逻辑移位==
==而对于有符号型值 ,算术左移等同于逻辑左移,算术右移补的是符号位,正数补0,负数补1。==

算术移位指令有:算术左移SAL(ShiftAlgebraic Left)和算术右移SAR(ShiftAlgebraic Right)。它们的指令格式如下:SAL/SAR Reg/Mem, CL/Imm,受影响的标志位:CF、OF、PF、SF和ZF(AF无定义)。算术移位指令的功能描述如下:

(1)算术左移SAL把目的操作数的低位向高位移,空出的低位补0;


(2)算术右移SAR把目的操作数的高位向低位移,空出的高位用最高位(符号位)填补。

  • 那么C编译器中采用的是那种移位方式呢?

在汇编指令中,shl和shr表示逻辑左移和逻辑右移,sal和sar表示算术左移和算术右移

#include <stdio.h>

int main()
{
    int a = 65;  //有符号整型 0100 0001
    unsigned int b = 65; //无符号整型 0100 0001
    a <<= 1; //1000 0010  130
    b >>= 1; //0010 0000  32
    char c = 127; //0111 1111
    c <<= 3; //1111 1000 -8
    char d = 127; //0111 1111
    d >>= 3; //0000 1111 15
    char e = -8; //内存以补码为1111 1000存储  源码为1000 1000 反码为1111 0111
    e >>= 3; //-1  补码1111 1111 源码 1000 0001 反码1111 1110
    printf("%d %d\n",a,b);//130 32
    printf("%d %d\n",c,d);//-8  15
    printf("%d\n",e);  //-1
    return 0;
}

让我们来看一看这一段代码的汇编代码

 

只看汇编代码进行分析:

汇编代码的第四行和第七行以及第十一行是对a,b,c三个变量进行的移位操作,即有符号型变量左移和无符号型右移C编译器都处理为逻辑移位,用的指令是shl和shr,移出的空位用0来补。

而对于汇编代码的第十五行和第十九行是对d,e两个变量进行的移位操作,即正数和负数的有符号型变量的右移,C编译器处理为算术移位,用的指令是sar,移出的空位,正数补0,负数补1。

对于C编译器的逻辑移位和算术移位的总结
我所使用的C编译器是VS2008,基于该编译器采用对无符号型int,short,char进行移位时,编译器默认生成的汇编指令是逻辑左移和逻辑右移。
而对于有符号的int,short,char进行移位时,左移还是逻辑左移,但右移时生成的汇编指令是算术右移。


参考:

https://blog.csdn.net/xzg_2017/article/details/80158215

https://www.cnblogs.com/hpcpp/p/6291710.html

算术移位逻辑移位和循环移位是计算机中常用的位移操作。它们的区别在于对于移位后的空缺位的填充方式不同。 1. 算术移位算术移位是指在移位时,保留符号位,移位后空缺的位用符号位来填充。例如,对于二进制数1011,进行算术右移一位,得到1101,左移一位,得到0110。 2. 逻辑移位逻辑移位是指在移位时,空缺的位用0来填充。例如,对于二进制数1011,进行逻辑右移一位,得到0101,左移一位,得到1010。 3. 循环移位:循环移位是指将二进制数的所有位进行循环移位,即移位后,最高位的数值会移动到最低位,其他位也按照相同的规则进行移位。循环移位分为带进位和不带进位两种方式。带进位的循环移位是指在移位时,最高位的数值会移动到最低位,并且会影响到进位位,其他位也按照相同的规则进行移位。不带进位的循环移位是指在移位时,最高位的数值会移动到最低位,其他位也按照相同的规则进行移位,进位位不受影响。 下面是三种移位操作的示例: 1. 算术移位 ```python # 算术右移 a = 0b1011 b = a >> 1 print(bin(b)) # 输出:-0b101 # 算术左移 a = 0b1011 b = a << 1 print(bin(b)) # 输出:0b10110 ``` 2. 逻辑移位 ```python # 逻辑右移 a = 0b1011 b = a >> 1 print(bin(b)) # 输出:0b101 # 逻辑左移 a = 0b1011 b = a << 1 print(bin(b)) # 输出:0b10110 ``` 3. 循环移位 ```python # 带进位的循环右移 a = 0b1011 b = (a >> 1) | (a << (4 - 1)) print(bin(b)) # 输出:0b1101 # 不带进位的循环右移 a = 0b1011 b = (a >> 1) | (a << (4 - 1)) & 0b1111 print(bin(b)) # 输出:0b1101 # 带进位的循环左移 a = 0b1011 b = (a << 1) | (a >> (4 - 1)) print(bin(b)) # 输出:0b0111 # 不带进位的循环左移 a = 0b1011 b = (a << 1) | (a >> (4 - 1)) & 0b1111 print(bin(b)) # 输出:0b0111 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值