Visual C++ >> Console
&&、&、||、|
表格
& | 位元AND運算(如:1 & 3 = 1) |
---|---|
| | 位元OR運算(如:1 | 3 = 3) |
&& | 邏輯AND判斷(如:1 && 3 = TRUE) |
|| | 邏輯OR判斷(如:1 || 3 = TRUE) |
上面這個四種符號是最基本的理解,但是,看看下面的程式,你可以知道差別在哪裡嗎?
volatile unsigned char x=0xff, y=0xff; int _tmain(int argc, _TCHAR* argv[]) { if(x && y){ x = 10; } if(x & y){ x = 10; } return 0; }
雖然從結果來看,這兩種寫法是接近的,但是,不能說哪一種寫法有問題,因為這兩種寫法要看使用者的應用動機是什麼,(x && y)可能有使用者要確定((x != 0) && (y != 0))條件成立才做,而(x & y)可能有使用者要確定((x & y) != 0)條件成立才做,一個是確定個別不等於0,另一個是要確定一起AND後不等於0,使用者對於這些基本邏輯、位元運算應該沒問題的。
司徒今天要針對這兩種寫法做比較深一點探討,因為C語言用久了,一般可能只會從結果看事情,看不到比較細膩一點的東西,所以只要翻譯成組合語言就可以一窺究竟
volatile unsigned char x=0xff, y=0xff; int _tmain(int argc, _TCHAR* argv[]) { 00411370 push ebp 00411371 mov ebp,esp 00411373 sub esp,0C0h 00411379 push ebx 0041137A push esi 0041137B push edi 0041137C lea edi,[ebp-0C0h] 00411382 mov ecx,30h 00411387 mov eax,0CCCCCCCCh 0041138C rep stos dword ptr es:[edi] if(x && y){ 0041138E movzx eax,byte ptr [x (417010h)] 00411395 test eax,eax 00411397 je wmain+3Bh (4113ABh) 00411399 movzx eax,byte ptr [y (417011h)] 004113A0 test eax,eax 004113A2 je wmain+3Bh (4113ABh) x = 10; 004113A4 mov byte ptr [x (417010h)],0Ah } if(x & y){ 004113AB movzx eax,byte ptr [x (417010h)] 004113B2 movzx ecx,byte ptr [y (417011h)] 004113B9 and eax,ecx 004113BB je wmain+54h (4113C4h) x = 10; 004113BD mov byte ptr [x (417010h)],0Ah } return 0; 004113C4 xor eax,eax }
(x && y)會先判斷x是否為0,若x=0,則不做後續判斷,而針對||來說,它也是一樣的效果,只要第一個成立就直接當作條件成立不做後續判斷,而(x & y)則是x AND y後,才判斷是否為0,若為0則成立,反之則不成立。
司徒這樣說,就跟沒說是一樣的,說穿了,其實&&的效能比&來得好(只要將運算元作適當安排),因為&&每次都會做測試判斷,一旦等於0(針對AND運算)就馬上跳出,而反觀&運算,則是需要從頭做一遍,最後才去判斷結果,所以邏輯判斷還是使用邏輯運算比較好,不要搞混亂用。
下面的程式使用者可以知道它的意思嗎?它並沒有寫錯,只是它是另有用途。
volatile unsigned char x=0xff, y=0xff; int _tmain(int argc, _TCHAR* argv[]) { if((x && y) && (x = 10)){ y = 20; } return 0; }
它的實際意思如下
volatile unsigned char x=0xff, y=0xff; int _tmain(int argc, _TCHAR* argv[]) { if(x && y){ x = 10; if(x > 0){ y = 20; } } return 0; }
它的意思就是(x && y)成立後,則設定x = 10,若x還是大於0,則設定y = 20,算是相當複雜,司徒不建議把程式寫得如此藝術化,司徒建議寫程式以保守安全不出錯為第一考量,畢竟多年後,自己再回頭看程式,搞不好自己也看不懂,更何況要交接給其他人,若交接給其他人,而他誤以為寫錯而改成((x && y) && (x == 10),那就真的是很難抓的Bug了。