这里先做一个前奏:
int a = 0xF0; //a = b1111 0000
a = a & (a - 1); //a = b1110 0000
a = a & (a - 1); //a = b1100 0000
a = a & (a - 1); //a = b1000 0000
a = a & (a - 1); //a = b0000 0000
上面这段程序可以发现这样的规律:a & (a - 1)这个操作的运行结果就是将数据a中的最低位的bit1清零,如果数据a中没有bit1,则该操作不影响数据a。
这样我们就可以使用这个操作做很多事情了,例如计算数据中有多少个bit1:
int count_bit1(int m)
{
int count = 0;
while(m)
{
m = m & (m-1);
count++;
}
return count;
}
如果一个数为2的n次方幂,那么这个数据的二进制数中只能有一个bit1,例如b0001、b0010、b1000等,所以使用上面的操作可以判断数据是否为2的n次方幂如下程序所示:
int is_number(int num)
{
if( m & (m - 1) == 0)
return 0;//如果一个数是2的N次方,返回0
else
return 1;//如果一个数不是2的N次方,返回1
}
What is the first (rightmost) 0 set?
rm0 = ~x & (x+1)
What is the first (rightmost) 1 set?
rm1 = x & -x;
How to get the offset of the first bit1 in a uint32_t var:
static int get_bitmask_offset(uint32_t bitmask)
{
uint8_t tbl[16] = {
4, // 0000
0, // 0001
1, // 0010
0, // 0011
2, // 0100
0, // 0101
1, // 0110
0, // 0111
3, // 1000
0, // 1001
1, // 1010
0, // 1011
2, // 1100
0, // 1101
1, // 1110
0, // 1111
};
int offset = 0;
while (bitmask) {
if (bitmask & 0xF) {
return offset + tbl[bitmask & 0xF];
}
bitmask >>= 4;
offset += 4;
}
return 0;
}
int test(uint32_t bitmask)
{
int cnt = 0;
while (bitmask) {
if (bitmask & 0x1) {
return cnt;
}
cnt++;
bitmask >>= 1;
}
return cnt;
}
int main() {
for (int i=0;i<100;i++) {
printf("%.8X %d %d\n", i, get_bitmask_offset(i), test(i));
}
}