我一直认为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
我错过了什么吗?
答案 0 :(得分:2)
在C ++中,这将是一个未定义的行为 * ,因为有多个未经过序列的分配。
在C#中,这是完全有效的,零是正确的结果。
为了理解为什么认为对任何数字进行异或运算产生零,因为在比特模式中的每个运动都有相等的比特。而且,XOR顺序并不重要。这就是为什么B最终得到A的旧值,A最终为零。
无论如何,在C ++ 17之前* 。