2011-08-28 67 views
7

我今天开始阅读“Programming Pearls”,在做练习时我遇到了这个问题“你将如何实现自己的位向量?”。当我看着它的解决方案是这样的:编程珍珠下面程序中的位掩码用法

#define BITSPERWORD 32 
#define SHIFT 5 
#define MASK 0x1F 
#define N 10000000 

int a[1 + N/BITSPERWORD]; 

void set(int i) { a[i >> SHIFT] |= (1 << (i & MASK)); 

当我收到的困惑是这种说法

1 << (i & MASK) 

可能有人请给我解释一下这是怎么回事呢?

回答

4

注意MASK被设定为使得它具有最低SHIFT位设置,其中SHIFT恰好的BITSPERWORD基2对数。

因此(i & MASK)将选择i的最低5位,这与除以32后的余数相同(考虑如何用十进制数的最低两位数除以100后给出余数,例)。这使该位数内一个字,我们感兴趣的问题。

1 << (i & MASK))(这是顺便说一下,一个表达,不是声明)现在创建一个值,完全位我们感兴趣的是设置。将此值与|=合并到内存字中将设置位向量的所需位。

+0

感谢Henning的回复。如果我用'(i%32)'替换'(i&MASK)''这会有效吗?如果它是有效的但不是优雅的,那么你能否说出为什么'i&MASK'比'i%32'更受欢迎?非常感谢。 – test123

+0

是的 - 只要你确定'我'不是负面的,''我&MASK'和'I%32'是同样的事情。按位AND通常比具有余数的分组更高效,因此已成为传统选择。或者至少当编译器愚蠢的时候,它会被更高效地利用。今天,你甚至可以期望即使是一个适度优化的编译器,在这种情况下内部重写'i%32'到'i&31'(它可以证明'i'不是负数,在这种情况下重写总是安全的,或者它无论如何,可以推断出一个负面结果会引发转变中的未定义行为)。 –

+0

太好了。非常感谢解释。 – test123

2

0x20是32,所以i & 0x1F需要i模32,所以你永远不会移位32位。这是一种保障措施,因为通过任何并非严格小于该类型大小的内容进行转移都是未定义的行为。

+0

感谢您的回复Kerrek! – test123