2013-07-19 204 views
16

爲什麼下面提到的程序的輸出是0而不是20關係運算符是否影響賦值運算符操作?

#include <stdio.h> 

int main() 
{ 
    int i = 10, j = 0; 
    if (i || (j = i + 10)) 
     /* do something */;     
    printf("%d\n",j); 
} 
+21

短路布爾表達式。 – jxh

+1

這可能看起來像一個愚蠢的問題,但我正在學習 - 程序如何輸出20?這與C具體有關嗎? – Andy

+1

@Andy **(1)** - 只有當'i = 0'(改變執行表達式'j = i + 10')時,程序才能輸出'20'。 **(2)**不,這個代碼在C++中是有效的,即使在Java中也是如此,因爲我們都可以在if()中執行'='並且都支持短路。 ---這將是有趣的,甚至不知道[Python支持短路](http://stackoverflow.com/questions/2580136/does-python-support-short-circuiting/14892812#14892812),但這種表達'如果(我||(j = i + 10))'在Python中無效,因爲'if'中的'='是語法錯誤。 –

回答

27

是,則概念被稱爲Short-Circuit(以邏輯&&||運營商表達)。

一旦結果評估(並保存執行),在任何邏輯表達式(包括||,&&)的情況下編譯器停止評估表達式。

短路的技術是:

!0 || any_expression == 1,所以any_expression不需要評估。

而且因爲在你的表達式中i不是0而是它的10,所以你可以認爲如果consular (i || (j = i + 10))就像i一樣。

邏輯或操作:
||運營商保證左到右的評價;在評估第一個操作數之後有一個 序列點。如果第一個 操作數比較unequal0,則第二個操作數是not 評估。

同樣,對於& &(和操作員):
0 && any_expression == 0,所以any_expression並不需要評估。

在你的表達:

(i || (j = i + 10)) 
     ------------ 
    ^
     | Could evaluate if i is 0, 
     as i = 10 (!0 = true), so j remains unchanged as second operand is not evaluated 

對於或||運營商的回答可以是0,1,爲了節省執行,評估,一旦結果發現停止。因此,如果第一個操作數不爲零,則結果將爲表達式的1(如上所示)。因此,對於第一個操作數i = 10將不等於0進行比較,則不評估第二個操作數(j = i + 10)因此j仍然爲0因此,您的代碼的輸出爲0

注意:短路行爲不僅存在於C語言中,而且許多語言(如Java,C++,Python)的概念都是常見的。 (但不是全部,例如VB6)。

在C中,保證邏輯表達式的短路一直是C的一個特性。當Dennis Ritchie設計並實現C的第一個版本(在1989 C標準中仍然如此)並且在C99標準。

相關的職位:Is short-circuiting boolean operators mandated in C/C++? And evaluation order?

+9

老實說,時間太長了答案。 – Antonio

+9

*「在任何一個邏輯表達式大多數編譯器停止評價表述的,一旦評估結果(以節省執行)的情況下。」 * - 不,它不是由*「大多數編譯器」 *完成的,而是由*所有*說稱自己是C編譯器,因爲它是由標準強制的。所以往往這不僅僅是爲了表現而是爲了正確,考慮'while(node && node-> value)',如果標準沒有*保證* short-cirtuiting,這將是非常錯誤的。 –

+1

@ChristianRau我不同意你的看法。短暫獲得性能的原始目的。我完全理解'while(node && node-> value)'它短路的第二個好處。 –

20

||是一個short-circuit運營商 - 如果左邊的計算結果爲真,那麼右側並不需要進行評估。所以,就你的情況而言,由於i爲真,因此表達式j = i + 10未被評估。如果設置i爲0但是然後右手側進行評估,

+0

是此功能依賴於編譯器? –

+3

@TheJoker不,在C邏輯表達式的短路保證一直是C的功能 –

+1

@保羅謝謝:) –

5

if (i || (j = i + 10)),有兩個布爾表達式。事情是,第一個是真的,因此不需要計算第二個。它完全被忽略。

3

因爲||是短路操作(因此是&&操作符)。

所以在(i || j = i+10)i是10的||左半部分是真實的,表達j = i+10沒有發生,因此,j=0