给定位掩码,如何计算位移计数

时间:2015-07-24 02:23:34

标签: c macros c-preprocessor

我想要一个函数或(最好)一个宏来计算获得某个位掩码所需的移位数。

目前我做的事情如下:

#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;
}

3 个答案:

答案 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)-1x&-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