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了。


返回上一頁