位運算的一個巧妙運用

for(x=0;x<DEVISIONS;x++)
for(y=0;y<DEVISIONS;y++)
 hwndChild[x][y]=CreateWindow(szChildClass,NULL,
   WS_CHILDWINDOW | WS_VISIBLE,
   0,0,0,0,
   hwnd,
(HMENU) (y << 8 | x),
   (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
   NULL);

  上面代碼對於一般入門者或者是很少接觸過位運算的同志,感覺這句代碼(上面藍色標記部分)真的很難理解,甚至看着頭痛!這是啥子呀?抓腦門……

其實如果分析開來並不難懂:這裏本來參數是“菜單”,但是對於子窗口來說,該參數稱爲“子窗口ID”,是一個用來唯一標識子窗口的數值。

MSDN中有說明:

hMenu [in]

     Handle to a menu, or specifies a child-window identifier depending on the window style. For an overlapped or pop-up window,hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used.For a child window,hMenu specifies the child-window identifier,an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.

既是說明子窗口ID是一個int類型咯…

這個ID是用戶自己定義滴,但是注意,不要撞車喔,要不然會很悲劇!

那就說明它是4個字節32位咯…(VC++6.0)

好,迴歸正題:

在上面的藍色標識代碼中,其實就是用來定義ID滴(有人吐槽:定義一個ID而已,有必要弄出那麼多個雞巴符號麼?額~~)。

當然,人家有道理的。爲了防止撞車,所以才巧妙的運用了位運算的知識

(y<<8 | x)其實就是把x和y一起合成子窗口ID的,怎麼合成?

1.y<<8其實就是把低八位向左移,然後低八位都補0。

假如int y = 1;那麼二進制就是 0000 0000 0000 0000 0000 0000 0000 0001;(額……不用算了,就31個0,其實可以省略的,不過爲了突出32位,哎…);

那麼y<<8 就是                         0000 0000 0000 0000 0000 00010000 0000

2.再看 (y<<8 ) | x,

假如 int x = 2;那麼二進制就是0000 0000 0000 0000 0000 0000 0000 0010;

那麼現在就簡單啦:

用y<<8的結果和上面的進行或運算得:0000 0000 0000 0000 0000 0001 0000 0010;

(運算規則請看前面章節,有詳解)。

那麼這樣,就完成了把x和y的組合了,y存在9~16位,x存在1~8位(也不知道是從哪邊開始算,我就大概從右算起吧…哎,學藝不精啊)而且只要x和y的範圍不超過…255吧應該,都不會出現子窗口ID撞車的現象。

而且以後需要x和y的值時,還可以通過位運算得出:

x=idfocus&0xFF;
y=idfocus>>8;

這個簡單了吧?就是上面的逆運算而已。說明一下0xFF是16進制的(感覺在說廢話),也就是(省略24個0)1111 1111

x=idfocus&0xFF;就是取低八位數據賦值給x。其它高位的都是0了。

y=idfocus>>8;就是把9位以後的右移八位,高八位都補0哈。然後賦值給y了。如果是上面的數據,那麼結果就是從

0000 0000 0000 0000 0000 0001 0000 0010到

0000 0000 0000 0000 0000 0000 0000 0001

 

總結一下:通過巧妙的位運算可以高效率的解決一些問題,可以把若干個數據保存到各個位上面組合,以後可以通過簡單的位運算取出!(又是廢話……別砸~)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章