C/C++中的移位运算你真的搞懂了吗?一文看懂移位运算 |
您所在的位置:网站首页 › 负数位运算右移 › C/C++中的移位运算你真的搞懂了吗?一文看懂移位运算 |
移位运算,很多人都是知道,但是又没有完全懂。这是因为移位运算的规则还是稍微有点复杂。因为移位运算分有左移、右移,同时还得区分逻辑移位和算术移位,并且还需要考虑移位超出数据长度的情况。 1 概念区分首先,左移、右移和算术移位、逻辑移位是交叉的关系,并不是四个并列关系。可以这么讲,左移和右移都可以分为算术移位、逻辑移位,也可以反过来将,算术移位、逻辑移位里面都可以分为左移、右移。所以这几个概念没有办法分开讲。 左移与右移:就是将数据整体左移,然后最左边的位(最低位)被丢弃,最右边的位(最高位)空出来,称为缺位。右移恰好相反。如下图所示(为了方便,以4bit数据为例): 算术移位与逻辑移位:这个两个的本质区别在于移位(右移)之后如何填充缺位。 对于逻辑移位,缺位一律填充0。对于算术移位,缺位填充符号位,即非负数填0,负数填1对于非负数来讲,符号位为0,因此算术右移之后,缺位填充0,与逻辑右移一样,因此,非负数的逻辑右移与算术右移结果一样。 通过以上的分析,可以得出如下结论: 左移 ,算术左移和逻辑左移结果一样,不用区分。右移,如果是非负数,算术右移和逻辑右移结果一样,不用区分。右移,如果是负数,算术右移和逻辑右移结果不一样。 2 编译器如何选择是逻辑移位还是算术移位我们在编码的时候,可以用> 分别表示左移和右移,但是编译器是如何区分这是算术移位还是逻辑移位呢? 如果是左移,不用区分逻辑移位还是算术移位,因为结果一样。如果是右移,编译器需要根据数据的类型选择,如果是unsigned 类型(无符号),选择逻辑右移,如果是signed类型,选择算术右移。因此,如果是signed类型数据,想要进行逻辑移位,可以强转为unsigned和类型后进行移位。unsigned类型要想进行算术移位,可以强转为signed类型后进行移位。 3 移位位数超过数据长度了编译器如何处理?首先,我们编码时,无论是移位运算还是其它计算,都需要尽可能避免数据溢出,或者需要注意这点。一般,当移位的长度大于等于数据的长度时,编译器一般都会产生告警提示。如果真的移位长度m超过了数据长度len,编译器是怎么处理的呢? 如果是左移,常量和变量处理不同: 常量,移位长度超过数据长度,直接变为0 变量,实际移位长度为m %len,以32为int数据为例,如果左移40位,实际上移位 40 % 32 = 8位右移的话,按照规则补位即可。 一个例子下面通过一个例子,直观感受不同情况下移位的结果: #include using namespace std; int main() { /* 左移: 1.不区分逻辑移位和算术移位,一律低位补0,高位丢弃 2.当移位长度大于数据类型长度时,如果是常量,结果为0,若是变量,移位长度对数据长度取余 */ int a = 1; cout |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |