在vc++編程中,會發現微軟的不少API裏面都用到了位運算,好比這個函數:c++
CreateWindowExA( __in DWORD dwExStyle, __in_opt LPCSTR lpClassName, __in_opt LPCSTR lpWindowName, __in DWORD dwStyle, __in int X, __in int Y, __in int nWidth, __in int nHeight, __in_opt HWND hWndParent, __in_opt HMENU hMenu, __in_opt HINSTANCE hInstance, __in_opt LPVOID lpParam);
這是windows API裏面建立窗口的函數,第四個參數dwStyle,表示窗口風格,窗口風格固然會有不少種, 並且不少種之間也是能夠組合的,那麼到底怎麼樣用一個參數表示這麼多中風格以及這些風格之間的組合呢?注意到了在寫程序的時候這個參數常常是這樣的:編程
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU ,很明顯這個參數能用或運算組合在一塊兒,咱們在VS中右擊轉到定義, 發現WS_CAPTION這些宏其實都是一個16進制的數字, 是如WS_CATION, 跟蹤發現WS_CAPTION實際上是WS_BORDER和WS_DLGFRAME或運算結果,WS_BORDER = 0x00800000L,WS_BORDER,dwStyle這個參數歸根接地都是由WS_BORDER這樣最基本的風格位運算組合的。windows
windows中DWORD爲32位,咱們仔細研究發現, 每種最基本的窗口風格如WS_BORDERz換換成二進制爲100000000000000000000000,發現其32位中只有一位爲1, 對應其餘風格也都相似只有一位爲1。假如窗口風格有32種(固然沒那麼多),那麼dwStyle參數32位的每一位對應一種風格, 這一位爲1就有這個風格, 爲0 就沒這個風格,這樣咱們就能經過位運算將不一樣的風格組合在一塊兒或者去掉某種風格。在建立窗口的時候只須要解析出dwStyle對應的每一位是否爲1咱們就能知道是否要包含這種風格。說了這麼多來看看個人代碼吧:函數
//判斷DWORD對應位是否爲1 //b爲須要判斷的數, i爲對應的位數 BOOL TestDword(DWORD b, DWORD i) { ATLASSERT(i <= 31); return (b&(0x01<<i))==0?FALSE:TRUE; } //將某一位置爲1或者0 //p爲須要改變的數的指針,i爲須要置0的位數
//state爲0或者1, //其也只能爲0或1(二進制每一位不是0就是1) void SetDWBit(DWORD* p, int i, DWORD state) { ATLASSERT(i <= 31 && (state == 0 || state == 1)); if (state == 0) *p &= ~(0x01<<i); else *p |= 0x01<<i; }
上文中個人代碼由於是在ATL下寫的因此用的ATLASSERT,你們沒有使用ATL的能夠本身改掉。注意到函數中我都是用0x01移位操做的。TestDword判斷某一位是否爲1, SetDwBit將對應的某一位置爲0 或者1。有了這兩個函數咱們就能很方便的在本身的代碼中使用位運算。好比咱們能夠用一個DWORD(32位)型變量表示某個對象對應的是否有32個狀態,注意此處個人第二個參數是位數是對應0到31的因此須要0x01<<i這個操做, 當讓咱們也能夠像windows同樣定義出每種風格 0x00000001(0x01<<0),0x00000010(0x01<<1),0x00000100(0x01<<2)...,上面函數只須要稍改下就好。spa
不少時候咱們均可以用一個變量表示不少種狀態,而不須要爲每種狀態定義一個變量,這樣咱們的程序會更簡潔更高效。以上函數用到位運算,若是不熟悉位運算的能夠本身查資料。有什麼錯誤請你們指出。指針