本节书摘来自华章计算机《C语言编程魔法书:基于C11标准》一书中的第2章,第2.8节,作者: 陈轶 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.8 移位操作
现代处理器的计算单元中一般都会包含移位器。移位器往往能执行算术左移(Arithmetic Shift Left)、算术右移(Arithmetic Shift Right)、逻辑左移(Logical Shift Left)、逻辑右移(Logical Shift Right)、循环右移(Rotational Shift Right)这些操作。
下面我们将分别介绍这些移位操作,这里需要提醒各位的是,移位操作一般总是对整数数据进行操作,并且移入移出的都是二进制比特。然而,不同的处理器架构对移位操作的实现可能会有一些不同。比如,如果对一个32位寄存器做移位操作,倘若指定要移动的比特数超过了31,那么在x86处理器中是将指定的比特移动位数做模32处理(也就是求除以32的余数,比如左移32位相当于左移0位、右移33位相当于右移1位);而在ARM、AVR等处理器中,对一个32位的整数做左移和逻辑右移超出31位的结果都将是零。
2.8.1 算术左移与逻辑左移
由于算术左移与逻辑左移操作基本是相同的,仅仅对标志位的影响有些区别,所以合并在一起讲。左移的操作步骤十分简单,假设我们要左移N位,那么先将整数的每个比特向左移动N位,然后空出的低N位填零。图2-10展示了对一个8位整数分别做左移1位与左移2位的过程。
图2-10中间由小写字母a~h构成的方格图即表示一个8位二进制整数,每个小写字母表示一比特,并且字母a作为最高位比特,字母h作为最低位比特。左移1位后,原来的8位二进制数就变成了bcdefgh0;左移2位后,原来的8位二进制数就变成了cdefgh00。
2.8.2 逻辑右移
逻辑右移的操作步序是:先将整数的每一个比特向右移动N位,然后高N位用零来填补。图2-11展示了一个8位二进制整数分别逻辑右移1位和2位的过程。
图2-11中间由小写字母a~h构成的方格图即表示一个8位二进制整数,每个小写字母表示一位比特,并且字母a作为最高位比特,字母h作为最低位比特。将原始二进制8位数据逻辑右移1位后,二进制数据变为0abcdefg;逻辑右移2位后,二进制数据变为00abcdef。
2.8.3 算术右移
算术右移与逻辑右移类似,只不过移出N位之后,高N位不是用零来填充,而是根据原始整数的最高位,如果原始整数的最高位为1,那么移位后的高N位用1来填充;如果是0,则用0来填充。图2-12展示了一个8位二进制整数分别算术右移1位和2位的过程。
图2-12中间由小写字母a~h构成的方格图,即表示一个8位二进制整数,每个小写字母表示一位比特,并且字母a作为最高位比特,字母h作为最低位比特。将原始8位二进制整数算术右移1位之后,该二进制数变为aabcdefg;将它算术右移2位之后,变为aaabcdef。
2.8.4 循环右移
循环右移的步序是:先将原始二进制整数右移N位,移出的N位依次放入到高N位。图2-13展示了将一个8位二进制整数分别循环右移1位和2位的过程。
图2-13中间由小写字母a~h构成的方格图,即表示一个8位二进制整数,每个小写字母表示一位比特,并且字母a作为最高位比特,字母h作为最低位比特。将原始8位二进制整数循环右移1位之后,该二进制整数变为habcdefg;将它循环右移2位之后,该二进制整数变为ghabcdef。