C++位运算详解(转)
位運算是對表示數據的基本單元進行"加和","減除"的方法.
?
首先一個位(bit)單位就是0或1,硬件表示就是一個肪沖的開和,這是硬軟通迅最基本的單元.我們所說的一個字節(byte)需要8個位來表示,一個字(WORD)要兩個字節,16個位表示.一個雙字(DWORD)要兩個字,四個字節,32個位來表示.
?0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0????
?|- ? bit ? 31??????????????????????...???????????????????????????? ??????bit ? 0 ? -??? |??
?|-? BYTE ? 3???-|? |-? BYTE ? 2?? -|?|- ?BYTE ? 1?? -|? |-??BYTE??0??? -|????
?|--------- ? WORD ? 1 ??? --------|?|--------?? WORD ? 0????----------|??
?|----------------------------- ?? DWORD ?? -----------------------------|?
在C++中往往需要用字節,字,雙字來操作數據,然而使用這種二進數來顯示數并不是很方便,而使用十進制數顯示,不能化整,因此選擇使用16進制數來顯示數據,因為一個16進制數每個個位正好就是4個二進制位的表示,一個字節8位,一個16進制數4位表示,因此一個字節用兩個16進制數表示.據此,實際圖像運算時雙字指針比單字指針快,單字指針比字節指針快
?
8B+字符的ascII對照:
???????????? 8?????????????????? B??????????????????? +
十進制:?? 56?????????????????66???????????????? 43
16進制: ?38???????????????? 42???????????????? 2B
二進制:? ?0011 1000????0100 0010??? 0010 1011
使用位運算的好處是可以將BYTE, ? WORD ? 或 ? DWORD ? 作為小數組或結構使用。通過位運算可以檢查位的值或賦值,也可以對整組的位進行運算。
位運算有六種運算符可以使用:
??????? & ? ? ? 與運算 ?
? ? ? ? | ? ? ? 或運算 ?
? ? ? ? ^ ? ? ? 異或運算 ?
? ? ? ? ~ ? ? ? 非運算(求補) ?
? ? ? >> ? ? ? 右移運算 ?
? ? ? << ? ? ? 左移運算
與運算(&)??
雙目運算。二個位都置位(等于1)時,結果等于1,其它的結果都等于0。 ?
? ? ? ? 1 ? ? ? & ? ? ? 1 ? ? ? == ? ? ? 1 ?
? ? ? ? 1 ? ? ? & ? ? ? 0 ? ? ? == ? ? ? 0 ?
? ? ? ? 0 ? ? ? & ? ? ? 1 ? ? ? == ? ? ? 0 ?
? ? ? ? 0 ? ? ? & ? ? ? 0 ? ? ? == ? ? ? 0??
???
與運算的一個用途是檢查指定位是否置位(等于1)。例如一個BYTE里有標識位,要檢查第4位是否置位,代碼如下: ?
? ?
? BYTE ? b ? = ? 50; ?
? if ? ( ? b ? & ? 0x10 ? ) ?
? ? ? ? ? cout ? << ? "Bit ? four ? is ? set" ? << ? endl; ?
? else ?
? ? ? ? ? cout ? << ? "Bit ? four ? is ? clear" ? << ? endl; ?
? ?
? 上述代碼可表示為: ?
? ?
? ? ? ? ? 00110010 ? ? - ? b ?
? ? ? &??00010000 ? ? - ? & ? 0x10 ?
? ? ---------------------------- ?
? ? ? ? ? 00010000 ? ? - ? result ?
? ?
? 可以看到第4位是置位了。 ?
? ?
? 或運算(|) ?
? 雙目運算。二個位只要有一個位置位,結果就等于1。二個位都為0時,結果為0。 ?
? ? ? ? 1 ? ? ? | ? ? ? 1 ? ? ? == ? ? ? 1 ?
? ? ? ? 1 ? ? ? | ? ? ? 0 ? ? ? == ? ? ? 1 ?
? ? ? ? 0 ? ? ? | ? ? ? 1 ? ? ? == ? ? ? 1 ?
? ? ? ? 0 ? ? ? | ? ? ? 0 ? ? ? == ? ? ? 0??
??????
??異或運算(^) ?
? 雙目運算。二個位不相等時,結果為1,否則為0。 ?
? ?
? ? ? ? 1 ? ? ? ^ ? ? ? 1 ? ? ? == ? ? ? 0 ?
? ? ? ? 1 ? ? ? ^ ? ? ? 0 ? ? ? == ? ? ? 1 ?
? ? ? ? 0 ? ? ? ^ ? ? ? 1 ? ? ? == ? ? ? 1 ?
? ? ? ? 0 ? ? ? ^ ? ? ? 0 ? ? ? == ? ? ? 0 ?
? ?
? 異或運算可用于位值翻轉。例如將第3位與第4位的值翻轉: ?
? ?
? BYTE ? b ? = ? 50; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? b ? = ? b ? ^ ? 0x18; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? b ? = ? b ? ^ ? 0x18; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? ?
? 可表達為: ?
? ?
? ? ? ? ? 00110010 ? ? - ? b ?
? ? ? ^??00011000 ? ? - ? ^0x18 ?
? ? ? ---------- ?
? ? ? ? ? 00101010 ? ? - ? result ?
? ?
? ? ? ? ? 00101010 ? ? - ? b ?
? ? ? ^??00011000 ? ? - ? ^0x18 ?
? ? ? ---------- ?
? ? ? ? ? 00110010 ? ? - ? result ?
? ?
??非運算(~)??
? 單目運算。位值取反,置0為1,或置1為0。非運算的用途是將指定位清0,其余位置1。非運算與數值大小無關。例如將第1位和第2位清0,其余位置1: ?
? ?
? BYTE ? b ? = ? ~0x03; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? WORD ? w ? = ? ~0x03; ?
? cout ? << ? "w ? = ? " ? << ? w ? << ? endl; ?
? ?
? 可表達為: ?
? ?
? ? ? ? ? 00000011 ? ? - ? 0x03 ?
? ? ? ? ? 11111100 ? ? - ? ~0x03 ? ? b ?
? ?
? ? ? ? ? 0000000000000011 ? ? - ? 0x03 ?
? ? ? ? ? 1111111111111100 ? ? - ? ~0x03 ? ? w ?
? ?
? 非運算和與運算結合,可以確保將指定為清0。如將第4位清0: ?
? ?
? BYTE ? b ? = ? 50; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? BYTE ? c ? = ? b ? & ? ~0x10; ?
? cout ? << ? "c ? = ? " ? << ? c ? << ? endl; ?
? ?
? 可表達為: ?
? ?
? ? ? ? ? 00110010 ? ? - ? b ?
? ? ? & ? 11101111 ? ? - ? ~0x10 ?
? ? ? ---------- ?
? ? ? ? ? 00100010 ? ? - ? result ?
? ?
? 移位運算(>> ? 與 ? <<)??
? 將位值向一個方向移動指定的位數。右移 ? >> ? 算子從高位向低位移動,左移 ? << ? 算子從低位向高位移動。往往用位移來對齊位的排列(如MAKEWPARAM, ? HIWORD, ? LOWORD ? 宏的功能)。 ?
? ?
? BYTE ? b ? = ? 12; ?
? cout ? << ? "b ? = ? " ? << ? b ? << ? endl; ?
? BYTE ? c ? = ? b ? << ? 2; ?
? cout ? << ? "c ? = ? " ? << ? c ? << ? endl; ?
? c ? = ? b ? >> ? 2; ?
? cout ? << ? "c ? = ? " ? << ? c ? << ? endl; ?
? ?
? 可表達為: ?
? ? ? ? ? 00001100 ? ? - ? b ?
? ? ? ? ? 00110000 ? ? - ? b ? << ? 2 ?
? ? ? ? ? 00000011 ? ? - ? b ? >> ? 2??
??????
? 位域(Bit ? Field) ?
? 位操作中的一件有意義的事是位域。利用位域可以用BYTE, ? WORD或DWORD來創建最小化的數據結構。例如要保存日期數據,并盡可能減少內存占用,就可以聲明這樣的結構: ?
? ?
? struct ? date_struct ? { ?
? ? ? ? ? BYTE ? ? ? day ? ? ? : ? 5, ? ? ? // ? 1 ? to ? 31 ?
? ? ? ? ? ? ? ? ? ? ? ? month ? : ? 4, ? ? ? // ? 1 ? to ? 12 ?
? ? ? ? ? ? ? ? ? ? ? ? year ? ? : ? 14; ? ? // ? 0 ? to ? 9999 ?
? ? ? ? ? }date; ?
? ? ? ? ? ?
? 在結構中,日期數據占用最低5位,月份占用4位,年占用14位。這樣整個日期數據只需占用23位,即3個字節。忽略第24位。如果用整數來表達各個域,整個結構要占用12個字節。 ?
? ?
? | ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? | ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? | ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? | ?
? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? | ?
? ? ? ? +------------- ? year ? --------------+ ? month+-- ? day ? --+ ?
? ?
? 現在分別看看在這個結構聲明中發生了什么 ?
? ?
? 首先看一下位域結構使用的數據類型。這里用的是BYTE。1個BYTE有8個位,編譯器將分配1個BYTE的內存。如果結構內的數據超過8位,編譯器就再分配1個BYTE,直到滿足數據要求。如果用WORD或DWORD作結構的數據類型,編譯器就分配一個完整的32位內存給結構。 ?
? ?
? 其次看一下域聲明。變量(day, ? month, ? year)名跟隨一個冒號,冒號后是變量占用的位數。位域之間用逗號分隔,用分號結束。 ?
? ?
? 使用了位域結構,就可以方便地象處理普通結構數據那樣處理成員數據。盡管我們無法得到位域的地址,卻可以使用結構地址。例如: ?
? date.day ? = ? 12; ?
? dateptr ? = ? &date; ?
? dateptr->year ? = ? 1852;
總結
以上是生活随笔為你收集整理的C++位运算详解(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 纯手法打骰子怎么练的
- 下一篇: 想找一本类似于pass绿卡图书的学霸笔记