web-dev-qa-db-ja.com

i = i ++はiをインクリメントしません。どうして?

重複の可能性:
なぜこれが無限ループに入るのですか?

i = i++のようなものは、CおよびC++で未定義の動作をします。これは、スカラーオブジェクトの値が、シーケンスポイントを介さずに、同じ式内で2回変更されるためです。

ただし、これらの種類の式は、C#またはJavaで明確に定義された動作をしていると思います。これは、引数の評価が左から右に行われ、シーケンスポイントがいたるところにあるためです。

そうは言っても、i = i++i++と同等であると思います。しかし、そうではありません。次のプログラムは0を出力します。

using System;
class Program
{
    static void Main(string[] args)
    {
        int i = 0;
        i = i++;
        Console.WriteLine(i);
    }
}

理由を理解するのを手伝ってくれませんか。

免責事項:上記の構成の動作が定義されているかどうかを十分に認識しています。それらはばかげて、役に立たず、読めなくて、不必要であり、コードで使用されるべきではありません。ただ興味があるだけ。

32
Armen Tsirunyan

動作はC#で明確に定義されており、評価順序は次のとおりです。

  1. 左側のiは変数iに評価されます
  2. 右側は0と評価され、iがインクリメントされます(現在はi==1
  3. 割り当てが実行され、iが0に設定されます(現在はi==0

最終結果はi==0

一般に、最初に式ツリーを作成します。それを評価するには、最初に左側を評価し、次に右側を評価し、最後にルートでの操作を評価します。それを再帰的に行います。

41
CodesInChaos

ポストインクリメント式の結果i++iの元の値です。だから後 i++が評価され(iをインクリメント)、iの古い値を...iに割り当てます。

使用するだけ

i++;

;)

18
Marc Gravell

i = ++iは、ここで起こっていると思うことを実行するコードです。 i++は実際には少し異なる動作をします。

i++を使用すると、iの値が増加しますが、i++の値はiの新しい値ではなく、以前の値です。したがって、i = i++を実行すると、「iの値を増やしてから、iを古い値に設定する」ということになります。

16
Jeremy Banks

さて、割り当てを行う前に、右側の式を評価する必要があります。これで、i++iの現在の値に評価され、その後iの値は1つ増加します。ただし、割り当てはまだ実行されていません。実行されると、i(1)の現在の値が、評価されたrhs式(この場合は0)で上書きされます。

主な違いは、++i(pre-increment、inew値に評価される)の間です。 afterインクリメント)およびi++、またはポストインクリメント。これは、ibeforeインクリメントの現在の値に評価されます。

代わりに++iを使用した場合、右辺の式は1と評価され、i == 1になります。

3