位元運算在 C 語言相當常見,這種寫法的優勢在於運算非常的有效率,但缺點是可讀性不高和寫法上有些許限制,因此,如果程式有執行效能瓶頸,可透過位元算算來提高運算效能
雖然上述的數據相當誘人,不過,還是建議效能關鍵處再使用上述的方式,否則後續維護上是一個問題。
===============================================================
var y : byte = x << 10;// Actual shift is 10 & (8-1) = 2
左移運算子<<
x << 1 即 x*2
x << n 即 x乘以(2的n次方)
x << n 即 x乘以(2的n次方)
右移運算子>>
x>>1 即x/2
x>>n 即 x除以(2的n次方)
x>>n 即 x除以(2的n次方)
位运算之左移右移运算之详解
================================================================================
執行結果如下:
0x7是C中整數的16進位寫法,其實就是10進位的7,將位元與1作XOR的作用其實就是位元反轉,0x7的最右邊三個位元為1,所以其實就是反轉 ch 的最後兩個字元,如下所示:
=> 01000001 => 65 'A'
01000110 => 70 'F'
before encoding:A after encoding:F decoding:A |
0x7是C中整數的16進位寫法,其實就是10進位的7,將位元與1作XOR的作用其實就是位元反轉,0x7的最右邊三個位元為1,所以其實就是反轉 ch 的最後兩個字元,如下所示:
01000001 | 65 (對應 ASCII的'A') |
00000111 | 0x7 |
01000110 | 70 (對應 ASCII中的'F') |
=> 01000001 => 65 'A'
01000110 => 70 'F'
xor:00000111=> 7 (加解密遮罩)
同樣的,這個簡單的XOR字元加密,要解密也只要再進行相同的位元反轉就可以了。
要注意的是,雖然在說明時都只取8個位元來說明,但實際的位元在運算時,需依資料型態所佔的記憶體長度而定,例如在使用int型態的0作運算時,要考慮的 是32個位元,而不是只有8個位元,因為int佔有4個位元組。
在位元運算上,C還有左移(<<)與右移(>>)兩個運算子,左移運算子會將所有的位元往左移指定的位數,左邊被擠出去的位元會被丟棄,而右邊會補上0;右移運算則 是相反,會將所有 的位元往右移指定的位數,右邊被擠出去的位元會被丟棄,至於左邊位元補0或補1則不一定,視系統而定。
二進制轉十進制:
例題一:00011101(二進制)轉十進制(八位元)
最左邊的數為0,得知此數是為正數
00011101=+(1*2^4+1*2^3+1*2^2+1*2^0)
=+(16+8+4+1)
=+29
例題二:11100011(二的補數)轉十進制(八位元)
最左邊的數為1,得知此數是為負數,且為二的補數
11100011(二的補數)-1=11100010(一的補數)
=-(1*2^4+1*2^3+1*2^2+1*2^0)
=-(16+8+4+1)
=-29
例題一:00011101(二進制)轉十進制(八位元)
最左邊的數為0,得知此數是為正數
00011101=+(1*2^4+1*2^3+1*2^2+1*2^0)
=+(16+8+4+1)
=+29
例題二:11100011(二的補數)轉十進制(八位元)
最左邊的數為1,得知此數是為負數,且為二的補數
11100011(二的補數)-1=11100010(一的補數)
=-(1*2^4+1*2^3+1*2^2+1*2^0)
=-(16+8+4+1)
=-29
2的補數轉換方法及差異
方法:
由以上得知十進制轉二進制如果為正數則直接化為二進制而如果為負數,
化為Sign-and-Magnitude則必須再最左邊加 1 來表示負數,若轉為二的補數,
則須經由一的補數的最右邊加 1 表示,另外二進制轉十進制一開始由最左
邊的數先辨別正負,如果是Sign-and-Magnitude正數則直接將 1 的數化為十
進制,如果為負數則將 0 的數化為負數,若是負數且為二的補數則一開始必
須減 1 來轉為一的補數再將 0 的數化為負數
兩者的差異:
轉為二的補數如果是負數,則保留從最右邊數過來的0,遇到第一個 1 則
將遇到的 1 以下數字保留其他 1 變 0 , 0 變 1 ,就轉為二的補數了,這
樣就可不用去運算一的補數
方法:
由以上得知十進制轉二進制如果為正數則直接化為二進制而如果為負數,
化為Sign-and-Magnitude則必須再最左邊加 1 來表示負數,若轉為二的補數,
則須經由一的補數的最右邊加 1 表示,另外二進制轉十進制一開始由最左
邊的數先辨別正負,如果是Sign-and-Magnitude正數則直接將 1 的數化為十
進制,如果為負數則將 0 的數化為負數,若是負數且為二的補數則一開始必
須減 1 來轉為一的補數再將 0 的數化為負數
兩者的差異:
轉為二的補數如果是負數,則保留從最右邊數過來的0,遇到第一個 1 則
將遇到的 1 以下數字保留其他 1 變 0 , 0 變 1 ,就轉為二的補數了,這
樣就可不用去運算一的補數
沒有留言:
張貼留言