编程基础:位运算06,左移
专栏导航
本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。
(一)WIn32 专栏导航
下一篇:编程基础:位运算07,右移
(二)MFC 专栏导航
下一篇:编程基础:位运算07,右移
本节前言
在之前的几个章节里面,我讲解了位运算中的基本运算类型。它们分别是按位与,按位或,按位取反,按位异或。这四种,算是几个基本的类型了。
从本节开始,我们要来讲解位运算中的最后一个部分,移位运算。
移位运算,在汇编语言里面,它包含的内容更为丰富。包括,逻辑左移,逻辑右移,算术左移,算术右移,循环左移,循环右移等等。其中呢,循环左移可以分为两种指令,循环右移也可以分为两种指令。
关于循环移位,这个,我们在本专栏里面,不予以展开。以后呢,我去开设汇编语言专栏的时候,我会去讲解循环移位的指令的。
而在本专栏里面,我们要去讲解的,是逻辑移位和算术移位。
逻辑移位比较简单,算术移位其实也很简单。但是呢,问题是,当我们用 C/C++ 的移位运算符【<<】和【>>】来执行程序指令的时候,它就显得有些复杂了。
复杂在哪儿呢?我们讲右移的时候,大家就会知道了。
本节,我们来讲解逻辑左移和算术左移。
一. 左移
逻辑左移和算术左移的执行效果,对于高级语言来讲是一样的。在本专栏里面,我们是在高级语言的层面讨论位运算,所以,我们将逻辑左移和算术左移,统称为左移。
由于执行效果一样,所以,在这里,我仅以左移为术语,来讲解逻辑左移和算术左移的知识。
左移,它是说,让某一个操作数里面的各个二进制位上的数,向高位移动若干个位。
在 C/C++ 里面,左移运算符为【<<】,不论是逻辑左移还是算术左移,它都是这个运算符。
我们来看一下这个运算的语法格式。
格式:左操作数 << 右操作数;
效果:左操作数的各个二进制位上的数,向左移动 [右操作数] 个数位。右边的空出的数位补 0,左边移出的数位,在高级语言层面,可以认为是被丢掉了。
注意事项:
移位操作可能引发数据溢出或精度丢失,需谨慎使用
在移位运算中,移动的位数 没有固定值 ,但实际操作中存在一些规则和限制。比如说,一般会有位数范围限制。移动位数
n必须满足0 ≤ n < 数据类型位数。例如,对于32位整数类型(如int),有效移位范围是0 ≤ n < 32。尝试移出所有位(如n << 32)或负数位(如n << -1)会导致未定义行为或运行时错误。本专栏里面,不讨论大于或等于数据类型位数的移位操作。想了解大于或等于数据类型位数的移位操作,请自行查阅资料。因为,这一块,我也不太懂。遇到了再说吧。在我的经验中,Linux 内核里面存在着移动位数超越数据类型位数的情况,以后遇到了再说。当前阶段里,我们仅仅研究移位的位数小于数据类型位数的情况。
接下来,我们把来看一个案例。
char ch01;
int num01, num02, num03;
char res01, res02, res03;
ch01 = 0x03;
num01 = 1;
num03 = 3;
num03 = 7;
res01 = ch01 << num01;
res02 = ch01 << num02;
res03 = ch01 << num03;
ch01 的值是 0x03,转换为二进制,它是 0000 0011 。
关于进制转换的知识,大家可以参考一下三个链接。
计算机基础:二进制基础04,十进整制数转化为二进制整数-CSDN博客
计算机基础:二进制基础13,十六进制与二进制的相互转换-CSDN博客
我们接着看代码。
res01 的运算,它是让 ch01 左移 1 位,结果为 0000 0110 。其十六进制形式为 0x06,对应的十进制值为 6 。
res02的运算,它是让 ch01 左移 3 位,结果为 0001 1000 。其十六进制形式为 0x18,对应的十进制值为 24 。
res03的运算,它是让 ch01 左移 7 位,结果为 1000 0000 。其十六进制形式为 0x80 。由于变量 res03 是一个有符号数,所以,补码 0x80 所对应的十进制的值,为 -128 。
这就是左移,很简单吧?
下一分节,我来讲左移的一个应用。
二. 左移的典型应用
左移的典型应用,是配合着按位与,按位或等等的基本位运算,来执行程序任务。
在本分节,我们会参考按位与,按位或,按位异或的一些个典型应用中的运算法则,如果你不熟悉,可以参考下方链接来学习。
我们接着往下讲。
(一)左移和按位与运算的结合
我们来看下面的案例。
short num01 = 0xFCAE;
num01 &= ~(1 << 3);
在这里,num01 的值为 0xFCAE,对应的二进制形式为 1111 1100 1010 1110 。
而程序的第二行的表达式用到了取反相与。取反相与,我们在讲解按位与运算的时候,我们说过了,它的法则是,0 位保留,1 位清零。
在第 2 行代码里,将 1 左移 3 位。1 转换为二进制形式的时候,它肯定会是处于位 0 这个数位上面的。将位 0 的 1 左移 3 位,它会移到位 3 上面,而其余位都是 0 。
所以,第 2 行代码的意思是,将 num01 的位 3 清零,其余位不变。
我们来推广一下,如果将第 2 行的 1 << 3 替换为 1 << 6,则执行效果就是:将 num01 的位 6 清零,而其余位保留不变。
如果将第 2 行的 1 << 3 替换为 1 << x,则执行效果就是:将 num01 的位 x 清零,而其余位保留不变。
(二)左移与按位或运算的结合
我们来看案例代码。
short num01 = 0xFCAE;
num01 |= 1 << 9;
1 << 9 。在这里,1 会被转化为二进制位 0 中的 1,左移 9 位以后,位 9 为 1,其余位都是 0 。
而之前在学习按位或运算的时候,我们了解到,位或的一个运算规律是,0 位保留,1 位置 1 。
它的意思,就是令 num01 的位 9 置 1,其余位不动。
(三)左移与按位异或运算的结合
short num01 = 0xFCAE;
num01 ^= 1 << 3;
1 << 3 。在这里,1 会被转化为二进制位 0 中的 1,左移 3 位以后,位 3 为 1,其余位都是 0 。
而之前在学习按位异或运算的时候,我们了解到,按位异或的一个运算规律是,0 位保留,1 位置取反 。
它的意思,就是令 num01 的位 3 取反,其余位不动。
结束语
左移的知识,我认为是不难的。
希望大家能够学好左移的知识。
专栏导航
本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。
(一)WIn32 专栏导航
下一篇:编程基础:位运算07,右移
(二)MFC 专栏导航
下一篇:编程基础:位运算07,右移
更多推荐
所有评论(0)