問題1在於你把==寫成了=。低級錯誤,不多說。

問題2在於+號兩側操作數的求值順序是一個unspecified behavior。對於表達式a + add(++a),是左邊的操作數a先被求值還是右邊的操作數add(++a)先被求值,是不能確定的。有些編譯器選擇先求a,另外一些選擇先求add(++a)。而求值順序直接影響到a的值是多少,如果左邊的a先被求值,那麼a的值是1,++a的值是2;而如果右邊的add(++a)先被求值,那麼++a的值是2,a的值也是2。因此,加法的結果是不能確定的,編譯器可能不會按照你預期的來工作。

遵循以下兩點準則,很容易避免這樣的問題:

  • 當一個對象多次出現在一個表達式中時,不要對其使用自增自減運算符
  • 當一個對象多次出現在函數的參數列表中時,不要對其使用自增自減運算符

以下是一些典型的反例:

y = x + (x++);

printf("%d %d
", --i, i++);

i = i++;

cout&請務必杜絕這樣的語句出現在你的代碼中。將你的表達式改為a + add(a+1),就可以得到正確的結果。


return 那句是未定義行為,編譯器可以做任何事情。


add(++a)可以理解為a+=1然後add(a)

問題在於你寫了a+add(++a),在同一個表達式里使用了一個被++過的變數

C++並不規定加號左右的計算順序,所以你不知道前面的a是+1前還是+1後的值

這樣的代碼叫undefined behavior, 未定義行為,意思是出來任何結果都沒有問題

所以即使你這麼寫出來的結果對了,也只是正好你用的編譯器生成出來了符合你預期的機器碼,不等於你的代碼是對的,換了一個編譯器可能就錯了


C/C++ 新手第二大關: = 和 == 的區別。

(PS. 第一大關:哪裡該打分號)


不應該在一個表達式里多次改變同一個變數的值。

對類似 + 這樣的二元運算符而言,先求左右兩側哪一個表達式,是未定義的(undefined behavior)。編譯器可能先對右側表達式求值,再對左側表達式求值,反之也有可能。

很多初學者把「求值順序」與「結合順序」混淆了,很多「老師」也是這樣。這樣,就會想當然地以為「左結合」的 + 是先對左側求值的。

函數調用里,先對哪一個表達式求值同樣是不一定的。這涉及到 calling convention 的問題。

不過,在新的 C++ 標準中,已經先進行自增賦值還是等號賦值的問題進行了規定,比如 i = ++i;

但是,總結地來看,「不要在一個表達式里對同一個變數賦值兩次」 的金科玉律仍然有效。

像這種兩個語句完全可以寫明白的代碼,非要擠在同一條語句里,這是 C 系語言的自增運算符帶來的一些誤用。本來這種運算符的存在是為了方便書寫,在存在運算符重載的語義下更是為迭代等功能提供了方便,可沒想到竟然被中國老師用作奇怪的考點。

新一代語言中,有的已經放棄了這種寫法。比如 Rust 語言,只能寫 a += 1。這樣,賦值語句只有一類,也不存在讓人糾結的先後問題了。

本來關於 ++ 的問題是月經貼了,但我看到題主是真心誠意地發問,所以還是希望這則回答能有所幫助。另外,善用 google, stackoverflow,遠離 baidu 等妙不可言的搜索引擎。


推薦閱讀:
相关文章