我有一些代码从数字中提取位:
uint32_t foo = getValue(); /*this just returns a value for `foo`*/
while (foo){
foo <<= 2;
doSomethingWithFoo(foo);
}
我担心我在这里有不确定的行为,因为我最终会超过&#34;过度移动&#34; foo
。我是对的吗?
答案 0 :(得分:4)
您的代码是安全的。
这是因为几个班次的行为是明确定义的(只要每个班次不会过多地改变)。从本质上讲,您在每次迭代时都会使用全新的foo
。
如果您尝试移动的位数多于一次性类型,则只会出现问题。
答案 1 :(得分:1)
没有未定义的行为,因为位移对变换数据的处理方式非常明确。您可以将位移视为一个窗口。例如下面的8位值,您可以:
b7 b6 b5 b4 b3 b2 b1 b0 1 0 0 1 1 0 0 1
上面的值是十六进制的0x99。如果我们向左移位1,我们最终会得到这个:
b7 b6 b5 b4 b3 b2 b1 b0 0 0 1 1 0 0 1 0
哪个是0x32。如果我们向右移位,我们就会得到这个:
b7 b6 b5 b4 b3 b2 b1 b0 0 1 0 0 1 1 0 0
哪个是0x4C。即使在极端情况下我们正在移位我们拥有的位数(在这种情况下为8),窗口上任何超出的值都是0,因此我们知道最终会得到0x00,如下所示。
b7 b6 b5 b4 b3 b2 b1 b0 0 0 0 0 0 0 0 0
因此,每个可能的场景都是由此操作定义的。
答案 2 :(得分:0)
您可以使用圆形左或右按位移位功能。
uint8_t circularLeftShift(uint8_t var, uint8_t numOfBits) {
if (numOfBits < 1 || numOfBits>7) return var;
uint8_t msb = 0;
for (int i = 0; i < numOfBits; i++)
{
msb = var & 128;
msb = msb >> 7;
var = var << 1;
var = var | msb;
}
return var;
}
uint8_t circularRightShift(uint8_t var, uint8_t numOfBits) {
if (numOfBits < 1 || numOfBits>7) return var;
uint8_t lsb = 0;
for (int i = 0; i < numOfBits; i++)
{
lsb = var & 1;
lsb = lsb << 7;
var = var >> 1;
var = var | lsb;
}
return var;
}