我想要一个函数或(最好)一个宏来计算获得某个位掩码所需的移位数。
目前我做的事情如下:
#define CURRBITMASK 0x30
#define CURRBITSHIFT 4
我想做什么:
#define BITMASK1 0x10
#define BITSHIFT1 GETSHIFT(BITMASK1) // 4 ; 0x10 = (0x1 << 4)
#define BITMASK2 0x18
#define BITSHIFT2 GETSHIFT(BITMASK2) // 3 ; 0x18 = (0x3 << 3)
#define BITMASK3 0xC0
#define BITSHIFT3 GETSHIFT(BITMASK3) // 6 ; 0xC0 = (0x3 << 6)
#define BITMASK4 0x40
#define BITSHIFT4 GETSHIFT(BITMASK3) // 6 ; 0x40 = (0x1 << 6)
有没有办法只使用宏从掩码中获得所需的移位? 如果没有,是否有更优化的方式将其作为一个函数而不是这个?:
int get_shift(int bitmask) {
int count = 0;
while (bitmask & 0x1) {
bitmask >>= 1;
count++;
}
return count;
}
答案 0 :(得分:1)
您的实现等同于计算数字中的尾随零的数量。
有几种方法可以解释here。其中一个示例通过七个步骤为32位数字执行此操作:
unsigned int v; // 32-bit word input to count zero bits on right
unsigned int c = 32; // c will be the number of zero bits on the right
v &= -signed(v);
if (v) c--;
if (v & 0x0000FFFF) c -= 16;
if (v & 0x00FF00FF) c -= 8;
if (v & 0x0F0F0F0F) c -= 4;
if (v & 0x33333333) c -= 2;
if (v & 0x55555555) c -= 1;
答案 1 :(得分:1)
This answer对我的问题给出了一个宏观解决方案:
/* Number of bits in inttype_MAX, or in any (1<<b)-1 where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
或者如果你想要更简单而不关心整数&gt; 2040-bit:
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
根据您的使用情况,您要传入的m
为(x&-x)-1
。 x&-x
剥离x
的最低位以外的所有位置,产生2的幂,然后减去1将这些宏放入正确的形式。
链接的答案链接到一个关于其工作原理的usenet帖子。
答案 2 :(得分:0)
我创建了一个不需要迭代步骤的快速解决方案。但是,您永远不知道要移位的位数,而是移位的n次方。然后通过乘法/除法完成移位,编译器将在移位时对其进行优化。
#define BITS2SHIFT(mask) (mask&-mask)
#define MOV2MASK(val,mask) (val*BITS2SHIFT(mask))&mask
#define MASK2VAL(val,mask) (val&mask)/BITS2SHIFT(mask)
有关使用方法,请参见此example。