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

C 给定位掩码,如何计算位移位计数,c,macros,c-preprocessor,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)

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

目前我做的事情如下:

#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)

您的实现相当于计算数字中尾随的零的数量

有几种方法可以做到这一点。对于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;
对于我的一个问题,给出了一个宏观解决方案:

/* 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))

/*inttype_MAX或any(1中的位数我创建了一个不需要迭代步骤的快速解决方案。但是,您永远不知道要移位的位数,而知道移位的n次方。然后通过乘法/除法进行移位,编译器将随着位移位进行优化

#define BITS2SHIFT(mask)                (mask&-mask)
#define MOV2MASK(val,mask)              (val*BITS2SHIFT(mask))&mask 
#define MASK2VAL(val,mask)              (val&mask)/BITS2SHIFT(mask)

查看如何使用它。

或者,
v&=-signed(v);
也可以是
v&=-v+1;
@Dmitri:相反,它应该是
v&=-v;
转换为
signed
充其量不起任何作用,最坏的情况下会破坏代码(在具有奇怪的实现定义的从无符号到有符号的转换的实现上).R..但是
v&=~v+1;
未转换为已签名(
v
已未签名)@Dmitri:事实上,对于未签名的两种形式都是相同的。我更喜欢
-v
,但
~v+1
是一样的。我不确定这是否适用于所有零的掩码。这或我使用不正确。掩码需要
1
s,否则它不是掩码?例如,将
01
放置在掩码
00110000
处将导致
 00010000
00000000
的掩码将导致零,我相信这段代码可以做到。或者正在以其他方式使用掩码?全部为0的掩码可能是一种抑制。我正在以您所述的方式使用它。我开始怀疑我的测试或生成系统存在问题,因为我的一些意外行为似乎在一个干净的b上消失了然而,0b00000001的掩码需要0的移位,这似乎从BITS2SHIFT返回1,我想这就是你在答案中概述的,但宏名称令人困惑。是的,这个名称有点含糊不清。它实际上是一个乘法器,0 bitshift乘以1。并且零掩码应该被抑制,因为
&mask
我认为这个名字+感冒+几个月来第一次不得不用二进制和十六进制数学思考足以让我彻底困惑:-P谢谢你澄清我的想法。
/* 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))
#define BITS2SHIFT(mask)                (mask&-mask)
#define MOV2MASK(val,mask)              (val*BITS2SHIFT(mask))&mask 
#define MASK2VAL(val,mask)              (val&mask)/BITS2SHIFT(mask)