什麼是位?
簡單來說,位就是1和0,在電腦中做的每一件事都是由它們組成的。電腦中所有的資料使用的是位。一個位元組由8個位組成;一個字由兩個位元組組成,即16個位;而一個雙字由四個位元組組成,即32個位。由於位元運算直接對記憶體資料進行操作,不需要轉成十進位,因此處理速度非常快
位元運算有哪些操作符?
& ,| ,~,<<,>>,^
(補充,邏輯運算子是 || , && , !這些和位元運算符大大不同)
它們分別的意思是:
& 與運算子 | 或運算子 ~ 取反運算子 >> 右移運算子 << 左移運算子 ^ 異或運算子
下面我們看看這些操作符是怎麼操作的:
&:
(1).運算規則:有0變0,無0為1
(2).判斷奇偶性
a&1 = 0 偶數
a&1 = 1 奇數
(3).可以用來取位操作
如:一個數 and 1的結果就是取二進位的最末位
(4).判斷一個數的二進位第n位是否為1的方法是:把一個n位為1,其它位為0與待判斷的數進行與運算
我們看下例子(看是否存在D盤,主要是根據與運算是否存在1000):
DWORD d = GetLogicalDrives();if((d&8)>0) //是否存在D盤{ SetDlgItemText(hwnd,IDC_EDTNAME4,TEXT("存在D盤"));}else{ SetDlgItemText(hwnd,IDC_EDTNAME4,TEXT("不存在D盤"));}
(5).求餘最佳化(x%(2n)=x&(2n-1))
| (或)
(1).運算規則:有1變1,無1變0
(2).一個數or 1的結果就是把二進位最末位強行變成1
~(取反)
(1).取反運算的定義是把記憶體中的0和1全部取反。使用not運算時要格外小心,你需要注意整數類型有沒有符號。如果not的對象是不帶正負號的整數(不能表示負數)。
如:
#include <stdio.h>int main(void){ unsigned short a=100; a = ~a; printf( "%d/n", a ); return 0;}
如上面的一段程式 算出來為 65435 而它的上界位65536 所以算出來的結果是它們的差,因為無符號類型的數是用$0000到$FFFF依次表示的。
<<(左移)
(1).如A<<B:是A轉換為二進位後向左移動B位
(2).左移3相當於乘以2的3次方
可以使用(1 << 16 )-1來表示個常量 如#defien Max_N (1 << 16 )-1, 因為這個值表示65535(很有用,有時大量的乘除運算可用移位代替,效率會很高!)
>>(右移)
(1).A>>B:是A轉換為二進位後向右移動B位
(2).右邊的位被擠掉。對於左邊移出的空位,如果是正數則空位補0,若為負數,可能補0或補1,這取決於所用的電腦系統。
(3).右移3相當於除以2的3次方
下面是個例子,看電腦中存在多少磁碟(主要是右移!)
void countIt(HWND hwnd){ DWORD n = GetLogicalDrives(); int count = 0;//計數器 while(n>0) { if((n&1)>0)//判斷最後一位是否為1 { count ++; } n = n>>1;//繼續右移 } TCHAR cD[256]; itoa(count,cD,10); MessageBox(NULL,cD,TEXT("hello!"),MB_OK); }
^:(異或)
1.可以用一句話理解:是不是不一樣 (不一樣為1,一樣為0)
2.兩次異或同一個數還是它本身(如:(a ^b)^b=a)
3.(a ^ b) ^ b = a,像這種異或運算可用於加密 用兩次異或 b位密碼
4.另外還有一個是不引入第三變數,交換兩個變數的值 (設 a=a1,b=b1)
5.兩個位元異或的結果為兩者之差的絕對值
一些位元運算的例子:
功能 | 樣本 | 位元運算 ----------------------+---------------------------+-------------------- 去掉最後一位 | (101101->10110) | x >> 1 在最後加一個0 | (101101->1011010) | x << 1 在最後加一個1 | (101101->1011011) | x << 1+1 把最後一位變成1 | (101100->101101) | x | 1 把最後一位變成0 | (101101->101100) | x | 1-1 最後一位取反 | (101101->101100) | x ^ 1 把右數第k位變成1 | (101001->101101,k=3) | x | (1 <<(k-1)) 把右數第k位變成0 | (101101->101001,k=3) | x & ~ (1 << (k-1)) 右數第k位取反 | (101001->101101,k=3) | x ^ (1 << (k-1)) 取末三位 | (1101101->101) | x & 7 取末k位 | (1101101->1101,k=5) | x & (1 << k-1) 取右數第k位 | (1101101->1,k=4) | x >> (k-1) & 1 把末k位變成1 | (101001->101111,k=4) | x | (1 << k-1) 末k位取反 | (101001->100110,k=4) | x ^ (1 << k-1) 把右邊連續的1變成0 | (100101111->100100000) | x & (x+1) 把右起第一個0變成1 | (100101111->100111111) | x | (x+1) 把右邊連續的0變成1 | (11011000->11011111) | x | (x-1) 取右邊連續的1 | (100101111->1111) | (x ^ (x+1)) >> 1 去掉右起第一個1的左邊 | (100101000->1000) | x & (x ^ (x-1))
位元運算求絕對值:
x >> 31是二進位的最高位,它用來表示x的符號。如果它為0(x為正),則~ (x >> 31) + 1等於$00000000,異或任何數結果都不變;如果最高位為1(x為負),則~ (x >> 31) + 1等於$FFFFFFFF,x異或它相當於所有數位取反,異或完後再加1。