位元運算子& AND, | OR, ^ XOR, ~ NOT @ 程式手扎 - 隨意窩
文章推薦指數: 80 %
邏輯運算子電路中最基本的邏輯運算子如下所列,可說是工程人員都耳熟能詳地,假設有A 和B 兩個bit,即它們的值只有0 和1 兩種,那麼A AND B 只有在兩者皆為1 的時候才 ...
程式手扎一些程式心得日誌相簿影音好友名片
關於我加入好友我的相簿我的影音
全部展開|全部收合
關鍵字
tsai.oktomy's新文章位元運算子&AND,|OR,^XOR,~NOTconst放置位置的意義SomecurrentinternallimitsofBDEC++的基本資料型態MFC程式結構基礎標準C++的類型轉換:static_cast、dynamic_castC/C++格式化#pragma設定Compiler模式關鍵詞__cplusplusextern"C"真實意義探討C++中extern“C”含義
tsai.oktomy's新回應沒有新回應!
巨人的肩膀程式手扎Tomy盤中日記
我的相簿
201303291406位元運算子&AND,|OR,^XOR,~NOT?C++
邏輯運算子
電路中最基本的邏輯運算子如下所列,可說是工程人員都耳熟能詳地,假設有A和B兩個bit,即它們的值只有0和1兩種,那麼AANDB只有在兩者皆為1的時候才會1,AORB則是兩者有ㄧ者為1的時候就會1,而AXORB是A與B不相等的時候為1,NOT則是單純地0變 1、1變0。
>>位元運算子
是將數值的位元向右移動n個位元。
向右移動後,超出儲存範圍的數字捨去,而左邊多出的位元就補上0。
<>
位元左移
位元右移
6
>
>=
<
<=
比較運算大於
比較運算大於等於
比較運算小於
比較運算小於等於
7
==
!=
比較運算等於
比較運算不等於
8
&
^
|
位元運算AND
位元運算XOR
位元運算OR
9
&&
||
邏輯運算AND
邏輯運算OR
10
?:
條件運算子
11
=
指定運算
而C/C++的位元處理運算子也是如此,不同的是這些運算子可以一次處理多個位元,例如unsignedchar有8bits,那麼:
unsignedchara=205(十進位)=11001101(二進位)
unsignedcharb=158(十進位)=10011110(二進位)
aANDb:c=a&b=140(十進位)=10001100(二進位)
在這個例子當中的&運算子就是C/C++的AND位元運算子,從這個例子可以看到&運算子分別對unsignedchar的8bits做了AND位元運算。
在之前你已經看過&出現在別的地方,其實習慣的話並不容易搞混的:
if(a!=0&&b!=0){...}//連續兩個&&是邏輯判斷的AND
if(a&&b){...}//同上
if(a&b){...}//這是AND位元運算,如果abitwise-ANDb的結果不為零...
char*ptr=&a;//&當一元運算子的時候是對變數取位址
總之C/C++有這四種位元運算子,可用於任何資料型別,意即該型別有幾個bits就做幾個bits的運算:
意義
運算子
範例
a
b
c
AND
&
c=a&b
11001101
10011110
10001100
OR
|
c=a|b
11001101
10011110
11011111
XOR
^
c=a^b
11001101
10011110
01010011
NOT
~
c=~a
11001101
00110010
2進位,10進位,16進位
請注意2進位/10進位/16進位只是(撰寫程式碼)的時候表示數值的格式,不是電腦儲存數值的格式。
電腦儲存數值一定是bitbybit的、也可以說一定是2進位的,但是了解不同進位之間的換算與表示法,仍然對寫程式大有幫助。
當我們說一個數字是205的時候,事實上我們經常隱喻了它是個10進位數字,我們之所以把這個數字寫成"205"是因為:
205(10進位)=2x102+0x101+5x100=cx161+dx100(16進位)=1x27+1x26+0x25+0x24+1x23+1x22+0x21+1x20(2進位)
如這個例子所示,我們所謂的2進位/10進位/16進位意思就是以2/10/16為底,所以205這個數字以16進位應該表示成cd,以2進位應該表示成11001101,把0~15之間的數以2進位/10進位/16進位列出如下表,其中16進位(Hex)以a~f代表10~15。
Dec
Hex
Binary
Dec
Hex
Binary
0
0
0000
8
8
1000
1
1
0001
9
9
1001
2
2
0010
10
a
1010
3
3
0011
11
b
1011
4
4
0100
12
c
1100
5
5
0101
13
d
1101
6
6
0110
14
e
1110
7
7
0111
15
f
1111
為甚麼要學習2進位與16進位呢?從這個表上你可以清楚地見到16進位每一個數字就恰恰好代表了4bits,例如0xcd=11001101:c(16進位)=1100(2進位)d(16進位)=1101(2進位)
所以我們只要一看到一個以16進位的數值,很直覺地就可以知道這個數字的各bit為何,因此在程式中以16進位來表示要進行位元運算(bitwiseoperation)的數字是非常方便的,否則就得換算了。
要在2進位/10進位/16進位之間換算,其實最佳的工具就是Windows內附的小算盤(calc.exe),如下圖,首先在檢視選單下,將小算盤切換到「工程型」,然後這個程式就會多出下圖密密麻麻的按鈕,接著選擇你要輸入數字的數值進制並且輸入數值,例如我要輸入10進位的205,所以我選擇了「十進位」然後輸入205,然後只要點選其他的數值進制,顯示的數字就會變成別的進制,例如在圖中我點選十六進制,205就變成了CD,點選了二進位,205就變成了11001101。
在C語言當中沒有二進位表示法與顯示格式,所以你沒辦法在程式東打一大串1001010101010101以二進位來指定數值,但是有16進位的表示法,也就是說你可以把你要運算的位元每4個為一組,以一個16進位的數字表示。
C語言的16進位表示法就是在數值前加上0x前綴字,編譯器變知道這個數值是16進位不是10進位,例如:
a=0xcd;//和a=205是一樣的
而printf()或其他的字串格式化與顯示函式都有16進位的顯示格式,就是%x(小寫顯示)或%X(大寫顯示)格式字串關鍵字,例如:
printf("%x",a);//顯示cd
printf("%X",a);//顯示CD
位元運算範例
下面這個例子展示了C語言中四種位元運算子的使用方法,請注意註解中的執行結果c,和原始數值a與b比較,就可知道這些運算子的效果。
#include
0x9527(16進位)=(二進位)
00000000000000001001010100100111
(00009527}
0xff00(16進位)=(二進位)
00000000000000001111111100000000
(0000ff00)
範例:
unsignedintx=0x9527;
unsignedinty=0xff00;
unsignedintq=x&y;
printf("%xAND%x=%x\n",x,y,q);
執行結果
9527ANDff00=9500
位元運算的應用
到這裡你可能會問,這些位元運算有甚麼用途呢?其實用途很多,比方說,例用AND運算子「a與b均為1的時候才會1」的性質,換言之「如果b為0的話,a不論多少、aANDb必定為0」,另一方面如果b為1,那麼aANDb就等於是a的原值,利用這個性質,就可以以b做為a的遮罩(mask),或稱做過濾器。
位元的AND運算非常地常用,在下圖中的黑白點陣圖(bitmap)影像,每個bit代表一個黑白像素(pixel),所以每個byte代表8bits,你可以看到左邊的影像是個V字,右邊的遮罩影像是個圓形。
把這兩個影像每個byte做AND的結果如下所示,等於是把V影像剪裁(crop)在圓形範圍之內了,所以V的兩支銳角不見了。
利用這個技巧,可以用AND去裁切掉影像不要的部分。
AND的運算的一個常見用途則是用在權限管理上,所謂使用者a對物品b的權限,應當是「a有權限使用物品、而b剛也有開放被使用的權限」的時候,a才得以使用b物品,如果a有使用物品的權限但是b不是公開物品,那麼a無法使用b物品,換言之,如果b是公開物品,但是a沒有使用任何物品的權限(比如權限等級只是訪客等級),a也不能使用b物品,所以很顯然地「a是否有權限使用物品b」是一個AND運算,舉個例子來說:
使用者OpenJohn的權限bits:00010011
意義000xxxxx→notowner
xxx100xx→可讀group文件
xxxxxx11→可讀寫公開文件
而
某檔案7-11.doc的權限遮罩:11111100
意義111xxxxx→owner可讀寫刪
xxx111xx→同group可讀寫刪
xxxxxx00→訪客不可讀不可寫
所以
OpenJohn對於7-11.doc的權限=AND結果:00010000
意義000xxxxx→notowner
xxx100xx→可讀此文件
xxxxxx00→不可讀寫此文件
這個技巧普遍地被各作業系統應用於使用者登入權限與檔案/目錄存取權限的管理與判讀。
除了AND運算以外,OR運算的特質在於「a與b只要有1者為1則a|b必定為1」,若b為0,則a|b則為a的原值,所以可說OR運算有「重疊」或「加法」的效果,相對於AND運算用於剪裁影像或判斷權限,OR運算則用於「影像重疊」或「賦予權限」,類似地,NOT運算可用於「影像反白」或「取得排除權限」或「取得遮罩」影像。
比較特別的是XOR運算,他的特色是「a和b不同的時候a^b才1,否則a^b必為0」,所以(a^b)^b等於a自己,以影像處理來說,A影像對B影像做XOR,會把B影像重疊在A之上(但是部分像素會反白),然後再對同一張B影像做一次XOR則能夠恢復A的原貌,所以XOR可以做到影像的「暫時」重疊(或移動中的影像),從前經常用於簡單動畫、滑鼠游標或輔助線的顯示上。
oktomy/Xuite日誌/回應(0)/引用(5)/好文轉寄沒有上一則|日誌首頁|沒有下一則回應
延伸文章資訊
- 1Not 運算子
此外,Not 運算子會將任何變數的位值逆轉,並根據下表在result 中設定對應的位。 如果bit in 運算式是, 結果中的位是. 0, 1. 1, 0 ...
- 2運算子
位元 ; AND, & ; XOR, ^ ; OR, | ; NOT, ~.
- 3位元運算子& AND, | OR, ^ XOR, ~ NOT @ 程式手扎 - 隨意窩
邏輯運算子電路中最基本的邏輯運算子如下所列,可說是工程人員都耳熟能詳地,假設有A 和B 兩個bit,即它們的值只有0 和1 兩種,那麼A AND B 只有在兩者皆為1 的時候才 ...
- 4位元運算- 維基百科,自由的百科全書
位元運算[編輯] · 1 位運算符. 1.1 取反(NOT); 1.2 按位或(OR); 1.3 按位異或(XOR); 1.4 按位與(AND) · 2 移位. 2.1 算術移位; 2.2 邏輯...
- 5位元NOT運算(~)
C++ 中位元補數運算(NOT) 的符號以~ 表示,~ 不像& 和|,而是對運算子右邊的單一運算元進行運算,位元補數運算會針對每一個位元進行二進制的補數 ...