1. ホーム
  2. c#

[解決済み】i = 0のとき、なぜ(i += i++)は0になるのですか?

2022-04-03 22:16:40

疑問点

次のようなコード(コンソールアプリケーションとして使用可能)を考えてみましょう。

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

の結果は i は0です。私は2を期待していました(私の同僚の何人かもそうでした)。おそらく、コンパイラが何らかの構造を作り、その結果 i がゼロになる。

i はすでに 1 なので、1 に 1 を足していることになります。明らかに、これは起こっていないことです。

コンパイラが何をしているのか、あるいは実行時に何が起こっているのか、説明できますか?なぜ結果が0になるのでしょうか?

免責事項: このコードを使用しない(そしておそらく使用すべきではない)ことは絶対に認識しています。私は決して使いません。それでも、なぜこのような動作をするのか、何が起きているのかを正確に知ることは興味深いことです。

解決方法は?

これです。

int i = 0;
i += i++

しているように見ることができます(以下は総花的な表現です)。

int i = 0;
i = i + i; // i=0 because the ++ is a postfix operator and hasn't been executed
i + 1; // Note that you are discarding the calculation result

実際に起こることはもっと複雑です。MSDNを見てみてください。 7.5.9 Postfix のインクリメントとデクリメント演算子 :

x++またはx--という形式の後置加算・減算操作の実行時処理は、以下のステップで構成される。

  • xが変数に分類される場合。

    • x が評価され、変数が生成される。
    • xの値が保存される。
    • 保存された x の値を引数として、選択された演算子が呼び出されます。
    • 演算子から返された値は、x の評価で指定された場所に保存されます。
    • 保存されたxの値が演算の結果となる。

ただし の優先順位は を使用すると、後置修飾子 ++ が発生します。 以前 += の前の値なので)結局使われないままです。 i が使用されます)。


の分解をより徹底して行う。 i += i++ を構成している部分まで知る必要があります。 +=++ は、そのように見えてもアトミックではない(つまり、どちらも単一の操作ではない)。これらの実装には、一時変数、コピーした i 操作の前に、それぞれの操作に対して1つずつ。(ここでは iAddiAssign に使用される一時的な変数に使用されます。 +++= をそれぞれ参照)。

ということは、より身近なところでは、次のようになります。

int i = 0;
int iAdd = i; // Copy of the current value of i, for ++
int iAssign = i; // Copy of the current value of i, for +=

i = i + 1; // i++ - Happens before += due to order of precedence
i = iAdd + iAssign;