昨天做点灯的程序突然出现了一个bug,LED为低电平点亮,我本想做一个灯顺着往下亮,但是每次都发现亮灯的数量是递增的,和我设想的不一样,我使用的是0xfe<<1的方法。
如果我改成 ~(0x01<<1)的方法就是正确的。
为什么会出现这种现象
我觉得可能和二进制的左移右移有关。后来通过C语言程序验证
经过两种方法验证后,可以看到如果二进制为 0000 0001,那么每次左移的结果就是 0000 0010,0000 0100……
但是如果是 1111 1110,那么左移的结果就是 1111 1100, 1111 1000……
据此可以知道,单纯的左移右移只是在移位后补0,所以对于0x01来说,左移结果就等于循环左移结果,而0xfe的左移结果就等于左移几位就补上几个零。
这是C语言中一个非常基础的问题,我现在才注意到,可见学习很不认真。
那么如何实现循环左移/右移
以a = 0xfe左移 i 位为例
a = 0xfe = 1111 1110D
可以增加一个变量 b 来保存a移位之后丢失的数据
b = a>>(8-i) //相当于把a即将丢失的 i 位数据保存到b中
a = (a<<i)|b = (a<<i)|(a>>(8-i))
即可实现循环移位
右移原理也是这样
公式总结
左移: a = (a<<i)|(a>>(X-i))
右移: a = (a>>i)|(a<<(X-i))
X表示总二进制位数,i表示位移位数