我有一个从数字中提取单个位的功能:
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)
答案 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)
这很有趣:)只需三个简单的步骤:
将您的价值调高lo
,并hi
减少lo
。这简化了“获得最低 hi 位”的问题。
剪掉最高位 - 动态创建自定义蒙版。
如有必要,请使用最高位对结果进行签名扩展(基于Sign extending from a constant bit width in C#进行bitfiddling)。
我不知道建议的函数原型的原因,但我建议使用订单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