この複合形式を使用すると、XOR による値の交換が失敗するのはなぜですか? 質問する

この複合形式を使用すると、XOR による値の交換が失敗するのはなぜですか? 質問する

XOR 演算子を使用して、3 番目の変数を使用せずに 2 つの数値を交換するコードを見つけました^

コード:

int i = 25;
int j = 36;
j ^= i;       
i ^= j;
j ^= i;

Console.WriteLine("i:" + i + " j:" + j);

//numbers Swapped correctly
//Output: i:36 j:25

ここで、上記のコードを同等のコードに変更しました。

私のコード:

int i = 25;
int j = 36;

j ^= i ^= j ^= i;   // I have changed to this equivalent (???).

Console.WriteLine("i:" + i + " j:" + j);

//Not Swapped correctly            
//Output: i:36 j:0

さて、私が知りたいのは、コードの出力が間違っているのはなぜですか?

ベストアンサー1

編集: 分かりました。

まず最初に指摘しておきたいのは、このコードは使用すべきではないということです。ただし、これを展開すると、次のコードと同等になります。

j = j ^ (i = i ^ (j = j ^ i));

( のようなより複雑な式を使用している場合はfoo.bar++ ^= i、 が 1 回だけ評価されることが重要になります++が、ここではより単純であると考えています。)

さて、オペランドの評価順序は常に左から右なので、まず次のようになります。

j = 36 ^ (i = i ^ (j = j ^ i));

これ(上記)が最も重要なステップです。最後に実行される XOR 演算の LHS は 36 になります。LHS は「jRHS が評価された後の値」ではありません。

^ の RHS の評価には「1 レベルのネスト」式が含まれるため、次のようになります。

j = 36 ^ (i = 25 ^ (j = j ^ i));

次に、ネストの最も深いレベルを見ると、iと の両方を置き換えることができますj

j = 36 ^ (i = 25 ^ (j = 25 ^ 36));

...これは

j = 36 ^ (i = 25 ^ (j = 61));

j最初に RHS への代入が行われますが、結果はいずれにせよ最後に上書きされるため、これを無視できます。j最後の代入の前に の評価はこれ以上行われません。

j = 36 ^ (i = 25 ^ 61);

これは次のものと同等になります:

i = 25 ^ 61;
j = 36 ^ (i = 25 ^ 61);

または:

i = 36;
j = 36 ^ 36;

それは次のようになります:

i = 36;
j = 0;

考えるすべて正しく、正しい答えにたどり着きます... 評価順序に関する詳細の一部が少しずれている場合は、Eric Lippert に謝罪します :(

おすすめ記事