位運算在驅動開發中是經常遇到的,尤其是置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次
a=a>>k|a<<16-k
#include <stdio.h>
int main()
{
printf("學習從來不是一個人的事情,要有個相互監督的夥伴\n");
printf("工作需要學習C/C++或者有興趣學習C/C++的夥伴可以家我球球
_2208165112\n");
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;
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
unsigned int i = 0x9f43bda5;
unsigned int ret = 0;
printf("i %x\n",i);
//將 i 第3位置1
ret = i | ( 1 << 3 );
printf("ret %x\n",ret);
//將 i 第2位置0
ret = i & ~( 1 << 2 );
//將 i 第4~9位置1
ret = i | ( 0x3f << 4 );
//將 i 第3~7位置0
ret = i & ~(0x1f << 3 );
//將 i 第1~7和9~11位置1
ret = i | ( 0x3f << 1 | 7 << 9);
//將 i 第2~8位置13~20位置0
ret = i & ~( 0x7f << 2 | 0xff << 13 );
位運算在驅動開發中是經常遇到的,尤其是置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++的夥伴可以家我球球
_2208165112\n");
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 %x\n",i);
//將 i 第3位置1
ret = i | ( 1 << 3 );
printf("ret %x\n",ret);
//將 i 第2位置0
ret = i & ~( 1 << 2 );
printf("ret %x\n",ret);
//將 i 第4~9位置1
ret = i | ( 0x3f << 4 );
printf("ret %x\n",ret);
//將 i 第3~7位置0
ret = i & ~(0x1f << 3 );
printf("ret %x\n",ret);
//將 i 第1~7和9~11位置1
ret = i | ( 0x3f << 1 | 7 << 9);
printf("ret %x\n",ret);
//將 i 第2~8位置13~20位置0
ret = i & ~( 0x7f << 2 | 0xff << 13 );
printf("ret %x\n",ret);
}