2012-07-06 58 views
0

我在代碼中發現了一個錯誤(if語句應該有「==」instad的「=」)並且我有幾個問題。如果語句中帶有等號「=」而不是「==」,則表達式

示例代碼:

int i = 5; 
if (i = MyFunction()) // MyFunction() returns an int; this is where bug was made 
{ 
    // call A() 
} 
else 
{ 
    // call B() 
} 

從我所收集它應該始終調用A()。
1.我的假設是否正確()?
2.這種情況是否適用於所有/大多數編譯器(任何例外情況)?

+4

如果'MyFunction'返回0,則調用B()' – teran 2012-07-06 09:27:41

回答

7
  1. 不,如果分配被認爲是真的,那麼它只會呼叫A(),即非零。
  2. 是的,這是標準的。由於混淆的風險很大,因此編寫代碼並不是一個好方法。

有人翻動比較,寫不斷的左側,以避免風險:

if(12 == x) 

但當然,這不會在你的情況很成功,因爲它確實是一項任務。當檢測到這些代碼時,大多數編譯器會給你一個警告,因爲它通常是錯誤的原因。

+2

這些翻轉的條件被稱爲「Yoda條件」(「如果12是計數,則執行此操作」)。見http://www.dodgycoder.net/2011/11/yoda-conditions-pokemon-exception.html – ollb 2012-07-06 09:36:48

+2

另外,自1990年以來,當Borland發佈了一個編譯器,該編譯器產生了「可能不正確的賦值」的警告時,yoda廢話已經過時。自那時以來,每一個體面的編譯器都有這個警告。所以不要混淆你的代碼,確保你得到一個編譯器警告。 – Lundin 2012-07-06 11:13:50

+0

@Lundin - 絕對是,很高興在這裏看到一些常識。我從未在職業生涯中犯過這樣的錯誤,我從未見過這是我職業生涯中的一次,有編譯器,靜態分析,代碼評論和測試等方面的東西來抓住這一點,最終通過讓尤達在鍵盤後面。我甚至已經看到這種火腿技術*像病毒一樣傳播*,以便編碼人員(顯然不理解表單的原始意圖)編寫諸如「if(4 Dan 2012-07-08 14:10:27

3

如果函數返回值不爲零,它將採用真正的分支(即調用A)。零被視爲假,因此如果MyFunction()返回零,它將調用B

實際上,對大多數/所有編譯器來說,這是正確的。我認爲0 =虛假只是一個約定;如果它現在已經在C99或更高版本中正式使用,我不會感到驚訝,但是我沒有副本可以方便地將您引薦到正確的部分。

5

如果MyFunction()返回零(0)它將調用B();否則它會調用A()。賦值表達式的值是分配給左側的值;在if語句中,0被視爲false,所有其他值都被視爲true。

這是完全合法的代碼,儘管許多編譯器會發出警告。它有效的原因是,在C語言和類似的語言中,賦值是一個表達式(而不是語句)。

如果您打算分配給i並測試返回值,則應該寫入if ((i = MyFunction()));額外的括號向編譯器(以及讀者)發出信號,指出分配的目的。

相反,如果你打算再次進行測試,你應該寫if (MyFunction() == i)i價值;通過將函數調用放在左邊,確保如果錯過了雙等號,代碼將無法編譯(MyFunction() = i通常不是有效的表達式)。

4

這種說法是賦值:

i = MyFunction() 

if語句實際上是檢查我的價值。如果MyFunction的()返回0,我被分配0,它變成相當於:

if(0) 

這個計算結果爲false,和A()將不會在這種情況下

3

你的假設是不正確調用。

if條件中的表達式與任何其他表達式一樣得到評估,在您的情況下,(i = MyFunction())的結果是MyFunction()的返回值。

2

您的代碼將評估

(i = MyFunction()) 

如果MyFunction()返回非零值,表達式將會爲真,並呼籲A()。否則,B()