重复按位移位

时间:2015-11-16 17:04:46

标签: c

我有一些代码从数字中提取位:

uint32_t foo = getValue(); /*this just returns a value for `foo`*/

while (foo){
    foo <<= 2;
    doSomethingWithFoo(foo);
}

我担心我在这里有不确定的行为,因为我最终会超过&#34;过度移动&#34; foo。我是对的吗?

3 个答案:

答案 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;
}