关于位操作
1. 不使用中间变量,交换a、b的值。
如使用:a = a + b; b = a - b; a = a - b;则当a、b都比较大时,a+b的值可能会溢出。而采用下述方法则没有溢出越界的问题:
a = a ^ b;
b = a ^ b;
a = a ^ b;
证明其实很简单,只要熟悉二进制运算就很容易了。令c=a^b,b(new)=c^b=a^b^b=a,a(new)=c^b(new)=a^b^a=b。
2. 计算一个整数对应二进制数中1的个数:
int num_of_1(int m)
{
int cnt =0;
while(m)
{
cnt++;
m = m&(m-1);
}
return cnt;
}
注:
(1)参数用int和unsigned int区别不是很大。
(2)m&(m-1)是消掉m最右面的一个1。
(3)一句话判断k是不是2的幂:if(!(k & (k-1)))
附加:
const UINT32 m1 = 0x55555555;
const UINT32 m2 = 0x33333333;
const UINT32 m4 = 0x0f0f0f0f;
const UINT32 m8 = 0x00ff00ff;
const UINT32 m16 = 0x0000ffff;
int count_1(UINT32 x)
{
x = (x & m1) + ((x >> 1) & m1);
x = (x & m2) + ((x >> 2) & m2);
x = (x & m4) + ((x >> 4) & m4);
x = (x & m8) + ((x >> 8) & m8);
x = (x & m16) + ((x >> 16) & m16);
return x;
}
3. 翻转一个字节
unsigned char reverse8 (unsigned char c)
{
c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
return c;
}
4. 如果一个字节的每一位代表一个状态,那么len个状态需要多少个字节
((len - 1) >> 3) + 1 /*len > 0*/
5. 如果字节数组的每一位代表一个状态,返回第i个状态(0,非0)
int ret_i_state(unsigned char * array, int i)
{
return array[i/8] & (1 << (i % 8));
}