web-dev-qa-db-ja.com

C、C ++、Java、およびC#での事前および事後の増分演算子の動作

免責事項:これは実際の例ではありません。これらの言語がどのように機能するかについての理論的な質問にすぎません。

C/C++、C#、およびJavaの違いは、ポストおよびプリインクリメント演算子に関しては正確には何ですか?

これは、VC++ 10、Java 1.6、およびC#4で得られるものです。

int a = 2;
int b = a++ + a++;
int c = ++a + a++ + a++;

      +-----+------+------+----+
      |  C  | C++  | Java | C# |
+-----+-----+------+------+----+
| a   |  7  |  7   |   7  |  7 |
+-----+-----+------+------+----+
| b   |  4  |  4   |   5  | 5  |
+-----+-----+------+------+----+
| c   | 15  |  15  |  16  | 16 |
+-----+-----+------+------+----+
57
Nick

JavaとC#は式を左から右に評価し、副作用が表示されます即時

C++では、部分式の評価の順序は規定されておらず、シーケンスポイントを間に挟まずに同じオブジェクトを2回変更することは、未定義の動作です。

63
fredoverflow

C++、C、C#、Java間のの違いの詳細な説明を書く時間はありません。前置および後置インクリメント演算子のC#の動作は完全に指定されている(シングルスレッドシナリオの場合、そのことについて知りたい場合は、原子性、マルチプロセッサの弱いメモリモデルでの読み取りと書き込みの順序の観察についての保証など、ユーザー自身が調査を行う必要があります。)CとC++では完全に指定されていません。コンパイラーは、副作用を並べ替えて自由に実行できる幅広い待機時間を持っています。私はJavaを使用したことがないので、Javaが何をするかについての推測を危険にさらすつもりはありません。

C#の詳細については、C#仕様を参照してください。簡単に言うと、この質問に対する私の答えを読んでください:

i ++と++ iの違いは何ですか?

さらに短いテイクの場合:

C#式の部分式は、優先順位と結合性によって論理的にグループ化され、左から右に関係なく評価されます。 (たとえば、A() + B() * C()はA()を評価し、次にB ()、次にC()。乗算が加算の「前に来る」という事実は関係ありません。部分式は常に左から右に評価されます。)

事前または事後のインクリメント式のために部分式の評価が副作用を引き起こす場合、副作用が発生します直前結果が生成されます。

33
Eric Lippert

C++では、これは未定義の動作であるため、anyの答えが正しいでしょう。詳細は 未定義の動作とシーケンスポイント を参照してください。

他の言語についてはわかりませんが、このコードも正しくないと思います。

編集:
C#に関するEric Lippertの回答をご覧ください。彼は、C#の動作についての私の仮定を否定します。

4
Vlad

C++では、少なくともこの未定義の動作です。 C++標準の引用:

前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトは、式の評価によって、格納された値を最大で1回変更します。

4
GWW

私はこの質問が好きで非常に良い説明を見つけましたが、この質問を評価する方法の価値によって説明したいだけです。

Javaおよびc/C++についてのみ説明します。C#についての知識がないためです。

ステートメントは次の方法で評価されます

Javaの場合

ステートメント|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||||||||||トレース

int a= 2;                     a=2
int b= a++ + a++;             a=2, a=3

here value of a=4

int c = ++a + a++ + a++;      a=5, a=5, a=6

here value of a=7

C/C++の場合

ステートメントトレース

int a= 2;                     a=2
int b= a++ + a++;             a=2, a=2

here value of a=4

int c = ++a + a++ + a++;      a=5, a=5, a=5

here value of a=7

つまり、Java式は左から右に進むため、2番目の "a"で新しい値がフェッチされ、c/c ++では最初に式全体が評価されてから、ステートメントのすべてのオペランドがインクリメントされます。

1
commit

Javaメモリモデルは、ロードとストアが行われる順序を保証するため、どのJVMでも同じようになるはずです(私は信じています)。

それはC++のように見えます 操作の順序は同じです ですが、1行で2回使用すると、他のものに実行し始めます(Vladはそこにあります)。他のC++コンパイラーを試すと、異なる答えが出てくる場合があります。

C#の操作順序は同じだと思いますが、一貫性を保証するメモリモデル(Javaなど)があると思いますが、ここでは多くの知識がありません。

1
MBCook