2017-07-02 176 views
0
#include <stdio.h> 

#define max(x,y)(x)>(y)?x:y 

int main() { 
    int i = 10; 
    int j = 5; 
    int k = 0; 
    k == max(i++, ++j); 
    printf("%d%d%d ", i, j, k); 
    return 0; 
} 

我知道答案。這是11 7 0但如何?請幫助我執行三元操作符。執行三元運算符

+6

使用具有副作用表達式的宏是一個_bad_想法。不要編寫這樣的代碼。注意:這與三元操作符無關。 –

+0

MSVC的'stdlib.h'已經有'max'宏 - 也許gcc也有它。 –

+1

你確定k == max(I ++,++ j)? '=='將檢查'k'是否大於0. –

回答

5

聲明

k==max(i++,++j); 

膨脹以

k==(i++)>(j++)?i++:j++; 

注意==具有較高的比precedence操作者?:,因此上述表達式是等效於

(k == ((i++)>(j++)))?i++:j++; 

由於(i++)>(j++)將爲true,因此k == ((i++)>(j++))被評估爲false,因此j++(且其值將變爲7)將被評估(將跳過i++)。


注:因爲存在三元運算符的第一操作數的評價和在第二或第三操作數之間sequence point上述表達式不調用未定義的行爲。例如,表達式

a = (*p++) ? (*p++) : 0 

具有良好定義的行爲。

+0

'10> 6'是'false'?怎麼會這樣? –

+0

@ Jean-FrançoisFabre;我的編輯錯了。 – haccks

+0

(10> 6)。它是錯誤的嗎? –

0

您正在使用雙等號,這是一個比較。 k==max(i++,++j);將max的返回值與k進行比較,該值爲0.

請改爲將==更改爲=

+0

這不是重點 –

+0

但這是一個很好的觀點。 –

2

這個問題絕對是一個難以捉摸的C程序員的絕招。不同的反應在這裏有超過100年的使用C複合經驗,但它採取了一些嘗試得到這個權利:

表達k == max(i++, ++j);擴展爲:

k == (i++)>(++j)?i++:++j; 

被解析,因爲這(==有的優先級低於>,但比?更高的優先級):

 (k == ((i++) > (++j))) 
    ? i++ 
    : ++j; 

三元運算符評估測試(i++)>(++j),這對於VA爲真因此評估爲1,與k的值不同,因此它繼續評估第三個表達式j++,其第二次增加j並返回中間值6。測試和分支之間有一個順序點,因此可以兩次增加j。第二個分支根本不執行,因爲測試評估爲false。

i遞增一次,其值變爲11

j遞增兩次,其值爲7

k沒有被上述語句修改,因爲==是比較運算符,而不是賦值運算符。

因此輸出爲11 7 0

注:

該程序使用的宏max計算結果超過一次它的參數更多,並且它們不能正確括號在膨脹:2級的錯誤,說明的缺點的宏。這個宏應該是名MAX強調一個事實,即它的參數應該不會有副作用,它的擴張應充分括號這樣:

#define MAX(x,y) ((x) > (y) ? (x) : (y)) 

一個更好的選擇是讓內聯函數:

static inline int max(int x, int y) { 
    return x > y ? x : y; 
} 

如果程序有這樣的說法:

k = max(i++, ++j); 

輸出將12 6 11因爲不像===?低優先級,因此語句將擴展爲:

k = ((i++) > (++j)) 
    ? i++ 
    : ++j; 

你可以學習的table of operator precedence for C。在我看來,有太多的層次,很難記住所有的層次,尤其是因爲其中有些層次非常直觀:打印一份並保持方便或製作書籤。如有疑問,請使用括號。

+1

表達式中沒有UB。 – haccks

+0

@haccks:是的,我改變了答案,測試和分支之間有一個順序點。 – chqrlie

+0

我已經在gcc上測試了代碼,並且讓我驚訝的得到了和OP –