2017-05-27 102 views
2

好吧,我知道表達式(x * = y = z = 4;)的輸出是40;但是我們究竟得到40呢?你能不能一步一步向我展示。解決複合賦值表達式

我以爲優先級從右到左左右(2×4)=(Z = 4),我不明白

#include <stdio.h> 
#define PRINTX printf("%d\n",x) 

int main (void){ 
    int x = 2, y, z; 
    x *= 3 + 2; 
    PRINTX; 
    x *= y = z = 4; 
    PRINTX; 
    x = y == z; 
    PRINTX; 
    x == (y = z); 
    PRINTX; 
    return 0; 
} 
+0

好的問題的方式。 – EJoshuaS

回答

4

不,分配在這裏可以評估的唯一方法是右到左。

首先,請注意,例如,x *= 99x = x * 99的簡寫。

隨着中說,

x *= y = z = 4; 

相當於

z = 4; 
y = z; 
x *= y; // This is shorthand for x = x * 4 

考慮,如果你想周圍的其他方法評估它會發生什麼:

// y is unininitialized 
x *= y; 
y = z; 
z = 4; 

它會失敗。

所以真的,

// x = 2 
int x = 2, y, z; 
// x = x * (3 + 2) = x * 5 = 2 * 5 = 10 
x *= 3 + 2; 

// x = x * 4 = 10 * 4 = 40 
x *= y = z = 4; 

這可以被改寫爲

int x, y, z; 
x = 2; // x = 2 
x = x * (3 + 2); // This is 2 * 5, so x = 10 after this 

z = 4; // z = 4 
y = z; // y = 4 
x = x * y; // x = 10 * 4 = 40 

這就是你如何結束了40

+0

謝謝,但我很困惑。你從哪裏得到5個?我認爲它是x * 4,x * = 3 * 2的地方;來自 – nonameisbetter

+0

@nonameisbetter我更新了。 '5'來自'3 + 2'。 'x * = 3 + 2'相當於'x * =(3 + 2)',相當於'x * = 5'。 – EJoshuaS

2

您有:

int x = 2, y, z; 
x *= 3 + 2; 

這是012的簡寫,如果x2開始,則其評估爲10

PRINTX; 
x *= y = z = 4; 

在此之後,y == z和都被設置爲4;並且x是其以前值10的4倍,因此40

PRINTX; 
x = y == z; 

此相比yz;他們是平等的,所以x被分配爲1(比較始終評估爲01)。

PRINTX; 
x == (y = z); 

此分配zy(離開值不變,4);名義上,這是與x比較,但編譯器可以忽略比較。因此,x不變,仍然1

+0

謝謝喬納森。我想我的困惑是我不知道這個問題要我們評估整個表達。我認爲這是一行一行 – nonameisbetter

+0

@nonameisbetter許多編程語言都有這樣的簡寫 - 有時如果簡寫混淆,試圖將其擴展爲等效的「更長」版本可能會有所幫助。我認爲這是一種速記沒有幫助的情況,因爲它使代碼更難閱讀。 – EJoshuaS

+1

@EJoshuaS:代碼是糟糕的代碼 - 它的唯一目的就是教學法,來測試你,讀者是否理解語言的規則。如果有人給我提供了這樣的代碼來審查,我會發送給他們,或者告訴他們錯誤的方式,或者盡我最大努力阻止它出現在主代碼中。混合任何'op ='賦值與簡單賦值相當醜陋。由於所有數字在這裏都是固定的,所以計算可以在編譯時完成。編譯器可以將代碼減少爲對具有預先計算值的'printf()進行的一系列4次調用。 –

3

所有賦值運算符具有相同的優先級和從右到左的關聯性(這會影響在表達式中存在多個具有相同優先級的運算符時發生的情況)。

這意味着x *= y = z = 4相當於x *= (y = (z = 4))。必須首先評估z = 4(其分配z4,並給出4的結果)。分配y = ...然後給出y的值4的值,並且還產生4的結果。轉讓x *= ...然後乘以x(其值爲10)乘以4,得出40的結果。

(原因x *= 3 + 2x10是,除了具有比分配更高的優先級,所以x *= 3+2相當於x *= (3 + 2)而非(x *= 3) + 2。)

如果分配經營者,而不是左到右結合, x *= y = z = 4將等於(((x *= y) = y) = z) = 4,它不會編譯。