A ^ = B ^ = A ^ = B; c#visual studio出人意料的结果

时间:2017-07-02 20:27:31

标签: c# c++ visual-studio visual-studio-2017

我一直认为A ^ = B ^ = A ^ = B交换A< - > B.我猜这一行应该从右到左分三步进行评估:

1) A ^= B;
2) B ^= A;
3) A ^= B;

但是如果你在一行中做某事,在C#A中会变成0。我查看了程序集,发现原始A是先存储的,为什么在最后的第三步而不是采用A的实际当前值,代码使用缓存的原始值。装配看起来像这样:

mov         eax,dword ptr [ebp-40h]  //eax <- A
mov         dword ptr [ebp-7Ch],eax  //C <- A (why cache?)
mov         eax,dword ptr [ebp-44h]  //eax <- B
xor         dword ptr [ebp-40h],eax  //A ^= B
mov         eax,dword ptr [ebp-40h]  //eax <- A
xor         dword ptr [ebp-44h],eax  //B ^= A
mov         eax,dword ptr [ebp-7Ch]  //eax <- C (?)
xor         eax,dword ptr [ebp-44h]  //eax ^= B (= C ^ B)
mov         dword ptr [ebp-40h],eax  //A = C ^ B (instead of A ^ B)

在C ++中似乎没问题,汇编只使用了2个变量:

mov         eax,dword ptr [a]
xor         eax,dword ptr [b]
mov         dword ptr [a],eax
mov         ecx,dword ptr [b]
xor         ecx,dword ptr [a]
mov         dword ptr [b],ecx
mov         edx,dword ptr [a]
xor         edx,dword ptr [b]
mov         dword ptr [a],edx

我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

在C ++中,这将是一个未定义的行为 * ,因为有多个未经过序列的分配。

在C#中,这是完全有效的,零是正确的结果。

为了理解为什么认为对任何数字进行异或运算产生零,因为在比特模式中的每个运动都有相等的比特。而且,XOR顺序并不重要。这就是为什么B最终得到A的旧值,A最终为零。

无论如何,在C ++ 17之前

*