首頁  >  問答  >  主體

c++ - 关于++运算符的一个问题

请问为什么下面代码输出的值为22?
求给出分析过程

#include<stdio.h>

int main(void)
{

    int i=5,j=5;

    int p;
 
    p=(++i)+(++i)+(++i);

    printf("p=%d",p);

    return 0;

}
天蓬老师天蓬老师2714 天前587

全部回覆(6)我來回復

  • 阿神

    阿神2017-04-17 15:33:45

    一個表達式裡面,同一個變數多個++的求值順序是不確定的,這種行為是未定義的,不同的編譯器可能會得出不同的結果,不建議寫出這樣的帶有副作用的程式碼。
    關於求值順序,可以參考wiki

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 15:33:45

    如果這是考題,請參考相關考試資料。


    在這裡給出C++11/14和C11正確的思路:

    表達式(++i)+(++i)+(++i)的相關順序規則有,先增的順序規則(副作用先於值計算)和運算子的順序規則(運算數的值計算先於運算子結果的值計算)。

    由此可確定的計算順序:在該表達式中,任意++i的副作用和值計算先於相關的+的值結算(+無副作用)且其副作用先於值計算(即先增)。根據+的結合性(由左向右)可得出:第一個+的值計算先於第二個+的值計算。

    不可確定的計算順序:任兩個++i的值計算和副作用之間均不存在確定的先後關係。

    所以憑直覺,可以根據上述限制,列出一系列可能的計算過程:

    6+7+8 = 13+8
    6+8+7 = 14+7
    7+6+8 = 13+8
    ...

    但問題在於,C++11/14標準中有以下約定:

    (§1.9/15)[...]If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value com effect on the same scalar object or a value coms effect value. , the behavior is undefined.

    C11標準中有下列約定:

    (§6.5/2)If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value.com undefined.[...]

    又因為該表達式中任兩個'++i'之間的副作用順序是未確定的,所以這在C++11/14和C11中是未定義行為。

    C++11之前和C11之前的規則在這裡不加討論,但根據其標準,也都是未定義行為。

    最後囉嗦一句未定義行為。 C++11標準有下列約定:

    (§1.3.24)undefined behavior
    behavior for which this International Standard imposes no requirements
    [Note: Undefined behavior may be expected when this International Standard orfiners Undefined havior may be expected when this explic en 活詞program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or programs execution inactr. tic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]

    C11標準有下列約定

    (§3.4.3)
    1 undefined behavior
    behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes Standard rements Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (withror outdronment. with the issuance of a diagnostic message).

    意即,標準對未定義行為的行為不做任何要求,而編譯器或運行平台可在編譯期或運行期約定未定義行為的行為也可不約定。在不約定時,程式的行為將完全無法預測。


    如果按譚爺(霧)的思路:(可能是)根據運算符+的結合方式(左結合),得出等價表達式

    。再推導出,左側兩個((++i)+(++i))+(++i)先計算(大霧),由於先增,等價++i,等價(7+7)+(++i)(大物),等於(7+7)+822

    問題在於,結合方式和子表達式的值計算順序沒有關係。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 15:33:45

    第一個++i參與運算的結果為6;第二個++i參與運算的結果為7,使第一個也變成了7;同理,第三個參與運算的結果為8,使前2個都變成了8,最後的結果是24.我用的是VS,這是用C++測的。

    同樣是VS,用C的結果如下圖

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 15:33:45

    樓上正解,所以撤了答案。

    如果你非要糾結這個問題,可以針對你使用的編譯器,將程式碼編譯成彙編,看看具體發生了什麼

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 15:33:45

    同意 @lianera 答案:這種運算C語言標準並沒有規定統一的運算順序。

    回覆
    0
  • PHPz

    PHPz2017-04-17 15:33:45

    額。 。說了那麼多,其實這問題壓根就不在計算順序上。 加法運算順序是從左到右。

    p=(++i)+(++i)+(++i);

    第一次加法的時候,猛一看是6+7.然而,第二個++i的自增使它前面(第一個++i)的那個i(6)也變成了7.那麼第一步運算的和是14.

    然後14加第3個i(8),就等於22了。

    這個答案僅限於配合SX教科書,實際應用中這麼寫打斷他的腿!當然不同的編譯器也會給他臉色。

    回覆
    0
  • 取消回覆