位操作網上有很多介紹,請上網google/baidu,比如:
位操作技巧實例大全:
http://blog.csdn.net/g_spider/article/details/5750665
位操作基礎篇之位操作全面總結
http://blog.csdn.net/morewindows/article/details/7354571
。。。
位操作C/C++或Delphi/pascal,其實都類似,只不過語言表達方式不同而已。
位操作 c/c++ delphi/pascal
與 & and
或 | or
非 ! not
異或 ^ xor
左移 << shl
右移 >> shr
要注意的是:D裡面的位操作(與或非)與邏輯操作的關鍵字是相同的,所以平時沒注意的話,可能就搞錯了。
下面,介紹一下俺平時的位操作,其它的技巧,請自行查資料:
一:標志位:and or not
置標志位有值: v := v or flag;
置標志位無值: v := v and not flag;
檢查是否有標志位有值:if (v and flag) = flag then 有值 else 無值.
其中:
1: v = Integer/Int64,即一個32或64位的數字(非浮點型)
2: flag 必須是2的N次方,(請用16進制8421助記),即:
$1, $2, $4, $8,
$10, $20, $40, $80
$100, $200, $400, $800
...
$10000000, $20000000, $40000000, $80000000
都是類似16進制,且,如果有"N個位"進行置位值,則flag = $1 or $2,這樣類似表示。
然後,看到這些,如果經常看Windows.pas的常量定義,就會發現,很多常量,就是這樣定義的。
為的就是,這個標志位進行取值,賦值,檢查值。
具體為啥這樣定義,請自行用計算器(二進制模式),進行and or not操作,慢慢摸:D
3: if (v and flag) = flag then 有值 else 無值.
一般這種寫法,我會省略為:
if (v and flag) <> 0 then 某值的標志位有值;
if (v and flag) = 0 then 某值的標志位無值;
然後,可以寫成多標志位:
const Masks = flag1 or flag2 or flag3....;
置多標志:x := v or Masks;
取值多標志:x := v and not Masks;
檢查多標志:if x and Masks <> 0 then ...
二:字節對齊:
字節對齊---對一個值,進行:不足則補足。如:
給出一個數:X,要對它進行對4補齊,則:
1:x = 5時,需要得到align(x) = 8,就是說8是x對4的補齊後的數字。
2:x = 16時,已經補齊,則align(x) = 16,即保持原值。
請注意:對齊數,必定為2的N次方。
上面的邏輯,寫成代碼就是:
x := 5;
a := 4;
x := (x + (a - 1)) and not (a - 1);
這樣,經過上述一行,and not 操作,x就與a對齊了。
我一般這樣簡寫:
x := (x + a - 1) and -a;
三:乘除法
用位移可以有限的代替乘除,因為只針對於被乘除數是2的N次方,如:
x * 2 ==> x shl 1
x * 4 ==> x shl 2
x div 8 ==> x shr 3
x div 16 ==> x shr 4
請看被乘除數:2,4, 8, 16,相當於2的1,2,3,4次方.
四:掩碼相關
取一個字節中的前4位:v := v and $0F;
取一個字節中的後4位:v := v shr $04;
那前3位,就是將前三位(以二進制數看)作掩碼,然後進行and:flag = $01 or $02 or $04; v := v and flag;
後3位,就自己想了。
五:根據三+四的法子,可以很方便的,使用and進行求模操作
求模操作在使用hash取索引值是:mod: index := abs(key mod len);
也可以這樣:
1:len = 2的N次方。
2:index := key and (len - 1);
六:一些小技巧:
1: 檢查某值是否為2的N次方:if (v and (v - 1)) = 0 then writeln('v是2的N次方');
2: 檢測某值是否偶數:if (v and 1) = 0 then writeln('v是偶數'); // 等同於:if v mod 2 = 0
3: 想到再加吧,有些也不常用,或者請到上面鏈接查看一些更詳細的技巧。
水平有限,如有雷同,就是盜鏈,:D
2014.11.02 by qsl