以下程序中的位掩码用法来自 Programming Pearls

Posted

技术标签:

【中文标题】以下程序中的位掩码用法来自 Programming Pearls【英文标题】:Bit Mask usage in the program below from Programming Pearls 【发布时间】:2011-11-05 08:01:44 【问题描述】:

我今天开始阅读“编程珍珠”,在练习时遇到了这个问题“你将如何实现自己的位向量?”。当我查看解决方案时,它是这样的:

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

有人可以解释一下这里发生了什么吗?

【问题讨论】:

【参考方案1】:

请注意,MASK 的设置使其具有最低的SHIFT 位设置,其中SHIFT 恰好是BITSPERWORD 的以2 为底的对数。

因此(i &amp; MASK) 将选择i 的最低5 位,这与除以32 后取余数相同(只需考虑取十进制数的最低两位如何得到除以后的余数100,例如)。这给出了我们感兴趣的单词 within 的位数。

1 &lt;&lt; (i &amp; MASK))(顺便说一句,这是一个表达式,而不是一个语句)现在创建一个值,其中我们感兴趣的位被设置.将此值与|= 合并到内存字中将设置位向量的所需位。

【讨论】:

感谢亨宁的回复。如果我随后将(i &amp; MASK) 替换为(i % 32),这是否有效?如果它有效但不优雅,那么您能否解释一下为什么i &amp; MASKi % 32 更受欢迎?非常感谢。 是的 -- i &amp; MASKi % 32 是一回事,只要您确定 i 不是否定的。按位与通常比带余数的除法更有效,因此已成为传统选择。或者至少它曾经在编译器愚蠢的时候更有效。今天,即使是适度优化的编译器也会在这种情况下在内部将i % 32 重写为i &amp; 31(或者它可以证明i 不是负数,在这种情况下重写总是安全的,或者它可以推断出一个负面结果无论如何都会在班次中触发未定义的行为)。 太棒了。非常感谢您的解释。【参考方案2】:

0x20 是 32,所以 i &amp; 0x1Fi 模 32,所以你永远不会移动 32 位。这是一种保护措施,因为任何不严格小于类型大小的移动都是未定义的行为。

【讨论】:

以上是关于以下程序中的位掩码用法来自 Programming Pearls的主要内容,如果未能解决你的问题,请参考以下文章

C中的位掩码

C++ 中有趣的位掩码谜题

Java位运算在程序设计中的使用:位掩码(BitMask)

Java位运算在程序设计中的使用:位掩码(BitMask)

选择位掩码中与选择器位图中的 1 位重叠的设置位范围

使用 SQLite 进行位掩码分组