位运算在驱动开发中是经常遇到的,尤其是置0和置1。既要指定的位数发生变化,又不能改变其它位的值,还要高效率的编写代码,这时候技巧就很重要了。在位运算中有几个符号: | 按位或 、& 按位与 、 ^ 异或 、~按位非。
应用技巧
1
判断int型变量a是奇数还是偶数
a&1 = 0 偶数
a&1 = 1 奇数
2
取int型变量a的第k位 (k=0,1,2……sizeof(int))
a>>k&1
3
将int型变量a的第k位清0
a=a&~(1<
4
将int型变量a的第k位置1
a=a|(1<
5
int型变量循环左移k次
(设sizeof(int)=16)
a=a<>16-k
6
int型变量a循环右移k次
(设sizeof(int)=16)
a=a>>k|a<<16-k
#include <stdio.h>
int main()
{
printf("学习从来不是一个人的事情,要有个相互监督的伙伴n");
printf("工作需要学习C/C++或者有兴趣学习C/C++的伙伴可以家我球球
_2208165112n");
return 0;
}
7
整数的平均值
对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:
int average(int x, int y) //返回X,Y 的平均值
{
return (x&y)+((x^y)>>1);
}
8
判断一个整数是不是2的幂,对于一个数 x >= 0
boolean power2(int x)
{
return ((x&(x-1))==0)&&(x!=0);
}
9
用位运算符交换两个整数
void swap(int x , int y)
{
x ^= y;
y ^= x;
x ^= y;
}
10
计算绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
11
取模运算转化成位运算 (在不产生溢出的情况下)
a % (2^n) 等价于 a & (2^n - 1)
12
乘法运算转化成位运算 (在不产生溢出的情况下)
a * (2^n) 等价于 a<< n
13
除法运算转化成位运算 (在不产生溢出的情况下)
a / (2^n) 等价于 a>> n
例: 12/8 == 12>>3
14
判断赋值
if (x == a) x= b;
else x= a; 等价于 x= a ^ b ^ x;
15
x 的 相反数
(~x+1)
技巧虽好,但是大家还是最好自己啃一啃才能知道味道呀,闲暇时,不防拿出来品一品,悟一悟其中的原理所在。
练一练
#include
int main()
{
unsigned int i = 0x9f43bda5;
unsigned int ret = 0;
printf("i %xn",i);
//将 i 第3位置1
ret = i | ( 1 << 3 );
printf("ret %xn",ret);
//将 i 第2位置0
ret = i & ~( 1 << 2 );
printf("ret %xn",ret);
//将 i 第4~9位置1
ret = i | ( 0x3f << 4 );
printf("ret %xn",ret);
//将 i 第3~7位置0
ret = i & ~(0x1f << 3 );
printf("ret %xn",ret);
//将 i 第1~7和9~11位置1
ret = i | ( 0x3f << 1 | 7 << 9);
printf("ret %xn",ret);
//将 i 第2~8位置13~20位置0
ret = i & ~( 0x7f << 2 | 0xff << 13 );
printf("ret %xn",ret);
}