为啥此语句在 java x ^= y ^= x ^= y 中不起作用;

Posted

技术标签:

【中文标题】为啥此语句在 java x ^= y ^= x ^= y 中不起作用;【英文标题】:Why is this statement not working in java x ^= y ^= x ^= y;为什么此语句在 java x ^= y ^= x ^= y 中不起作用; 【发布时间】:2011-04-20 04:26:11 【问题描述】:
int x=1;
int y=2;
x ^= y ^= x ^= y;

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

【问题讨论】:

这是 C 中未定义的行为,因为您在一个序列点中同时修改 x 和 y 两次。 不要使用它。使用额外的临时变量来交换 2 效率更高,因为它不必进行计算。 表达式x ^= y ^= x ^= y; 的行为是undefined in C。 IMre L:你完全错了。仅仅因为“计算”对我们人类来说需要更长的时间,没有理由假设它比计算机上的评估需要更长的时间。事实上,我敢打赌两者都需要同样长的时间。 XOR 是 CPU 能做的最简单的操作。 “正确”的措辞不正确。 【参考方案1】:

你的陈述大致相当于这个扩展形式:

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

与 C 不同,在 Java 中,二元运算符的左操作数保证在右操作数之前计算。评估发生如下:

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

您可以颠倒每个 xor 表达式的参数顺序,以便在再次计算变量之前完成赋值:

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

这是一个更紧凑的版本,也可以使用:

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

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

【讨论】:

你确定吗?我认为赋值返回 true,这就是为什么使用 = 而不是 == 的 if 语句总是运行?这意味着您的第一个陈述与 x=x^true^true; 相同 @Aaron,没有。 JLS§15.26:“在运行时,赋值表达式的结果是赋值发生后变量的值。”在 Java 中,旧的 = 而不是 if 条件中的 == 只有在变量是布尔值时才能编译。【参考方案2】:

Mark 关于它在 Java 中的评估方式是完全正确的。原因是JLS§15.7.2.,Evaluate Operands before Operation,和§15.7,需要从左到右求值:

它相当于(§15.26.2,复合赋值运算符):

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)

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

【讨论】:

以上是关于为啥此语句在 java x ^= y ^= x ^= y 中不起作用;的主要内容,如果未能解决你的问题,请参考以下文章

为啥以下语句在 Java 中给出不同的输出?

Java三元运算符语法[重复]

java 运算符,流程控制语句,键盘录入

为啥 x*=y 在 Python 中比 x=x*y 慢?

随机变量X,Y独立,则X²与Y²,X与Y²,X²与Y,等等为啥为啥都独立?

有关JAVA里if判断语句中 如果只为一个& 怎么理解?