以前在我看来,位运算是一个可有可无的东西,但是随着经验的积累,发现位运算有时候能有效的解决特定的问题,以及提高程序的效率,所以下面有几个比较实用的技巧供大家参考。
- 结构体中实现位段
c语言结构体可以实现位段,它的定义形式是在一个定义的结构体成员后面加上冒号,然后是该成员所占用的位数。位段结构体成员必须是int或者unsigned int类型,位段在内存中的存储方式是由具体的编译器决定的。
如下:
typedef struct
{
int aa:3 ;
}Test;
我们限定了成员变量aa为3位,因为是有符号类型,所以除去符号位,aa只能表示0-3的范围。当aa被复制为4的时候回这么样呢?
我们简单分析一下,首先t.aa=4,赋值后二进制aa=0100(B),由于aa只有3位,所以保留下来的是100(B),而首位是代表符号位的,也就是说系统认为这是一个负数,其绝对值为先减一为011,再取反码为100(B)=4(d),所以结果为-4.若将aa声明为unsigned int 则结果可以正确显示出4,但是超过7也会出问题。
2.加快某些计算
将某个数乘以2,可以利用位运算,cpu直接支持位运算,效率比乘法高,x*8可以用x<<3,同样x*7可以用(x<<3)-X来表示。
- 求平均值
(x+y)/2用位操作可以写为(x&y)+((x^y)>>1).第一部分是取x和y都有1的位,第二部分是取x,y不同的时候的部分,相加再除以2,所以最后是2个数的平均值。
- 求整数中二进制表示中1的个数
核心代码如下:
int fun(int x)
{
int count_x=0;
while(x)
{
count_x++;
x=x&(x-1);//核心语句
}
return n;
}
大家可以自己敲一下,看看是如何操作的。大致如下,如果x是一个奇数,进过一次操作后,减一,即左右边的位变为0,得到一个偶数,如果x是一个偶数,则每次循环后,x最靠右边的1变为0,即每次操作后,x二进制中的1都会少一个。如下图的例子。
以后可能会继续补充……