2017-10-13 123 views
0

我很好奇C標準關於條件子句中變量賦值的確切定義。這裏是一個小例子:在條件變量賦值後&&(C)

int foo() { 
    ... 
} 

int bar() { 
    ... 
} 

int main() { 
    int a, b, x, y; 
    ... 
    if ((a = foo()) == x && (b = bar() == y) { 
    ... 
    } 
    ... 
} 

與GCC的試驗表明,如果(a = foo()) != xb = bar()將不被執行。一方面,這種行爲是最佳的,因爲它不會浪費任何時間來計算bar()。但另一方面,b的值有些不確定,因爲它取決於foo()的結果,實際上它與b無關。

我想知道在C標準中是否存在這種情況的明確定義以及該定義的原因是什麼。最後,什麼被認爲是最佳實踐編寫這樣的代碼?

+4

查找「短路評估」 – Mat

+0

哪些情況?請詳細說明。 –

+0

如果'if'之後的代碼依賴於'b'被初始化,那麼「最佳實踐」就是不這樣做。 –

回答

0

這很簡單:&&第二(即右手)參數將如果第一個參數的計算結果爲0。

所以,(b = bar() == y)來,如果(a = foo()) == x是0評估進行評估。

事實上,這可能會使b未初始化 - 有可能未定義的結果 - 是您不應該用這種方式進行編碼這一事實的試金石。

可以使用

if ((a = foo() == x) & (b = bar() == y)) 

,如果你想雙方始終進行評估:&不短路。但是,如果參數可以評估爲0或1以外的值(在這種情況下它們不是這種情況),請注意意想不到的影響。

0

GCC測試顯示,如果(a = foo())!= x,b = bar()將不會執行。

那麼,這是邏輯AND(&&)運算符的屬性。

引用C11,章§6.5.13,重點煤礦

不同的是按位二進制&運算符,& &運營商保證左到右的評價; 如果評估第二個操作數,則在第一個和第二個操作數的評估之間有一個序列點。 如果第一個操作數比較等於0,則不計算第二個操作數 。

這就是說,對於的b分配,你是對的,如果第一個操作數是假的b值保持不確定和變量的任何使用可能會導致undefined behavior

(其中之一)最佳實踐,是根據定義初始化局部變量以避免使用不確定值。

0

運營商&&短路評估組成:第二個子表達式只有在需要其結果以確定整個表達式的結果時才被評估。


在您的例子,在表達式:

(a = foo()) == x && (b = bar() == y) 

如果第一子表達式(a = foo()) == x被評估爲假,上面的表達式的結果,無論是結果的還假該子表達式(b = bar() == y)將生產。

由於短路評估和(a = foo()) == x評估爲false的事實,因此不會評估表達式(b = bar() == y)