Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个语句在javax^=y^=x^=y中不起作用;_Java_Swap_Undefined Behavior_Xor - Fatal编程技术网

为什么这个语句在javax^=y^=x^=y中不起作用;

为什么这个语句在javax^=y^=x^=y中不起作用;,java,swap,undefined-behavior,xor,Java,Swap,Undefined Behavior,Xor,我希望这些值可以交换,但它给出了x=0和y=1。 当我尝试使用C语言时,它给出了正确的结果。您的语句大致相当于此扩展形式: int x=1; int y=2; x ^= y ^= x ^= y; 与C语言不同,在Java中,二元运算符的左操作数保证在右操作数之前求值。评估过程如下: x = x ^ (y = y ^ (x = x ^ y)); 可以反转每个xor表达式的参数顺序,以便在再次计算变量之前完成赋值: x = x ^ (y = y ^ (x = x ^ y)) x = 1 ^ (y

我希望这些值可以交换,但它给出了x=0和y=1。
当我尝试使用C语言时,它给出了正确的结果。

您的语句大致相当于此扩展形式:

int x=1;
int y=2;
x ^= y ^= x ^= y;
与C语言不同,在Java中,二元运算符的左操作数保证在右操作数之前求值。评估过程如下:

x = x ^ (y = y ^ (x = x ^ y));
可以反转每个xor表达式的参数顺序,以便在再次计算变量之前完成赋值:

x = x ^ (y = y ^ (x = x ^ y))
x = 1 ^ (y = 2 ^ (x = 1 ^ 2))
x = 1 ^ (y = 2 ^ (x = 3))
x = 1 ^ (y = 2 ^ 3)             // x is set to 3 
x = 1 ^ (y = 1)
x = 1 ^ 1                       // y is set to 1
x = 0                           // x is set to 0
这是一个更紧凑的版本,也适用于:

x = (y = (x = x ^ y) ^ y) ^ x
x = (y = (x = 1 ^ 2) ^ y) ^ x
x = (y = (x = 3) ^ y) ^ x 
x = (y = 3 ^ y) ^ x             // x is set to 3
x = (y = 3 ^ 2) ^ x
x = (y = 1) ^ x
x = 1 ^ x                       // y is set to 1
x = 1 ^ 3
x = 2                           // x is set to 2

但这是一种真正可怕的交换两个变量的方式。使用临时变量是一个更好的主意。

Mark完全正确地描述了它在Java中的计算方式。原因是JLS,在操作之前对操作数求值,并且需要从左到右求值:

它(通过复合赋值运算符)等效于:

我们从左到右求值,在运算之前执行两个操作数

x = x ^ (y = y ^ (x = (x ^ y)));

请注意,这在C中是未定义的行为,因为在序列点之间修改同一变量两次。

在C中是未定义的行为,因为在序列点中修改x和y两次。不要使用它。使用额外的temp变量交换2更有效,因为它不必进行计算=而不是
if
条件中的
=
x = x ^ (y = y ^ (x = (x ^ y)));
x = 1 ^ (y = y ^ (x = (x ^ y))); // left of outer 
x = 1 ^ (y = 2 ^ (x = (x ^ y))); // left of middle 
x = 1 ^ (y = 2 ^ (x = (1 ^ y))); // left of inner
x = 1 ^ (y = 2 ^ (x = (1 ^ 2))); // right of inner
x = 1 ^ (y = 2 ^ (x = 3)); // inner xor (right inner assign)
x = 1 ^ (y = 2 ^ 3); // inner assign (right middle xor)
x = 1 ^ (y = 1); // middle xor (right middle assign)
x = 1 ^ 1; // middle assign (right outer xor)
x = 0; // outer xor (right outer assign)