如何从C中的数字返回多个位

时间:2015-02-08 23:54:25

标签: c get return bits

我有一个从数字中提取单个位的功能:

int getBit (int value, int position) {

    return value & (1 << position));

    }

但我如何为一个范围(包括有符号和无符号数字)执行此操作?例如:

从0x12345678获取位10:14(带符号0)= 0x15

int getField (int value, int hi, int lo, bool isSigned)

3 个答案:

答案 0 :(得分:0)

你只需创建一个面具:

int createMask(int a, int b){
int c = a;
int mask = 0;
/*First we set the lenght of the mask*/
while(c <= b){  /*Including b*/
mask <<= 1;
mask = mask|1;
c++;
}
/*Then we set the position to the mask, the first bit is in the position 0*/
c=0;
while(c<a){
c++;
mask <<= 1 ;

}
return mask;
}

我还没有测试过这个功能,但它仅用于解释制作蒙版的方法。

最终的功能可能是这样的:

int getBits(int value, int a, int b){
int mask = createMask(a, b);
mask &= value;
//Now we have to move the bits to the right
while(a>0){
mask >>= 1;
a--;
}
return mask;

}

例如,如果你想要前6位,你必须编码:getBits(myValue,0,5)。

我不确定你对签名和无符号数字的意思是什么,但我希望它可以帮助你。

我的英语。

答案 1 :(得分:0)

我怀疑你可能想以不同的方式解决整个问题。而不是提取位,为什么不使用位掩码。

例如,要检查字节中的最高有效位是否已启用:

if(byte & 0xf0) {}

要检查最低有效位,它将是:

if(byte & 0x01) {}

要检查多个(或“范围”)位,请说低位半字节:

if(byte & 0x0f) {}

从你所说的,我怀疑这更接近你想要的东西,比转移提取位更简单。

答案 2 :(得分:0)

这很有趣:)只需三个简单的步骤:

  1. 将您的价值调高lo,并hi减少lo。这简化了“获得最低 hi 位”的问题。

  2. 剪掉最高位 - 动态创建自定义蒙版。

  3. 如有必要,请使用最高位对结果进行签名扩展(基于Sign extending from a constant bit width in C#进行bitfiddling)。

  4. 我不知道建议的函数原型的原因,但我建议使用订单lo, hi而不是hi, lo。不知怎的10,14感觉比其他方式更自然,即使从左到右计数从高到低的位数 - 计算机应该让我们更容易!

    #include <stdio.h>
    #include <stdbool.h>
    
    int getField (int value, int hi, int lo, bool isSigned)
    {
        /* step 1: clip off lower bits */
        value >>= lo;
        hi -= lo-1;
        /* step 2: clip off higher bits */
        value &= ~(-1<<hi);
        /* step 3: extend sign */
        if (isSigned && (value & (1<<(hi-1))))
            value |= -(1<<hi);
        return value;
    }
    
    int main (void)
    {
        int i;
        i = getField (0x123456c8, 14,10, true);
        printf ("i = %d / %Xh\n", i,i);
        return 0;
    }
    

    结果:

    i = -11 / FFFFFFF5h
    

    这是正确的位集:

      16   12    8    4    0 <- bit position
    ...4    5    6    7    8 <- value
    0100 0101 0110 0111 1000 <- bitwise
          --- --             <- mask
          101 01             <- result
     ..111101 01             < sign extended result