簡體   English   中英

向其自身添加變量,其后綴增量在Java / c#中與在C中不同

[英]adding variable to itself with postfix increment different in Java/c# than in C

在Java和C#中,如果我這樣做:

int i=1;
int j= i++ + i;

j為3,即轉換為1 + 2並在加法之前遞增i。

但是,在C中j是2,即它轉換為1 + 1,然后遞增i。

在C和Java / C#中導致這種表達式差異的內部機制是什么?

(修復后也一樣。Java/ C#變為4,C變為3。)

謝謝。

順便說一句,最初我以為這就是C答案,因此被Java / C#結果弄糊塗了。

與Java和C#明確指定發生副作用的時間不同,C禁止在下一個序列點之前使用具有副作用的表達式。 您的表達式不僅會在C中產生不同的結果,而且還是未定義的行為。

在C語言中,該機制是對微調的編譯器編寫技巧的一種慶祝,通常被稱為Undefined behavior或“ UB”。

換句話說,沒有人可以提供C的答案,因為預先知道該代碼會觸發未定義的行為。 任何事情都可能發生,沒有“正確”或“錯誤”。

2011年C語言標准草案開始

6.5表達式

...
2如果相對於相同標量對象上的不同副作用或使用相同標量對象的值進行的值計算,相對於標量對象的副作用未排序,則行為未定義。 如果一個表達式的子表達式有多個允許的排序,則如果在任何排序中都出現這種無序的副作用,則行為是不確定的。 84)

3語法指示運算符和操作數的分組。 85)除非后面有規定,否則子表達式的副作用和值計算是不順序的。 86)
84)本段呈現未定義的語句表達式,例如
\n     i = ++ i +1;\n     a [i ++] = i;\n
同時允許
\n     我=我+ 1;\n     a [i] = i;\n

85)語法指定了運算符在表達式求值中的優先級,該優先級與此子節的主要子節的順序相同,從最高優先級開始。 因此,例如,允許作為二進制+運算符(6.5.6)的操作數的表達式是6.5.1至6.5.6中定義的那些表達式。 例外情況是強制轉換表達式(6.5.4)作為一元運算符(6.5.3)的操作數,以及以下任何一對運算符之間包含的操作數:分組括號()(6.5.1),下標括號[](6.5) .2.1),函數調用括號()(6.5.2.2)和條件運算符? :(6.5.15)。 在每個主要子條款中,運算符具有相同的優先級。 左或右關聯在每個子句中由其中討論的表達式的語法表示。

86)在程序執行過程中被多次評估的表達式中,不需要在不同的評估中一致地對其子表達式進行無序且不確定排序的評估。

相對於較大的表達式i++ + i而言, i++的副作用施加的順序未指定 這兩個操作相對於彼此沒有順序。 如果在評估i++之后立即應用了副作用,那么您將得到1 + 2的結果。如果將副作用推遲到加法之后,您將得到1 + 1的結果。

該標准的較舊版本更加清晰。 一個對象最多可以通過評估序列點之間的表達式來修改其值一次 ,並且該表達式的先驗值僅用於確定要存儲的新值。

行為未定義,因此不需要編譯器來檢測這些問題並發出診斷信息( i++ + i很容易捕獲,但是此問題的細微變化要難得多)。 就語言定義而言,任何一個結果都是“正確的”。

在C語言中,當前操作完成后,將執行后遞增/遞減操作。 在此示例中,i ++ + i; 添加完成后,我將遞增。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM