一行的多个分配不按预期工作[英] Multiple assignment on one line not working as expected

问题描述

我在示例中尝试交换两个int s - x和y,并在没有库函数的情况下在一行中执行.

所以我开始了这个:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

y ^= x;

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

输出如预期为4, 3, 7, 3, 7, 4, 3, 4.到目前为止都很好.

下一个是:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

y ^= (x ^= y);

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

输出再次是预期的.到目前为止还不错.

然后最后是:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

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

System.out.println(x);
System.out.println(y);
在此阶段,输出变为4, 3, 0, 4.现在我知道0是4 ^ 4的结果,因为当时x赋值没有完成 - 为什么这发生了?为什么x ^= y实际上没有将7分配给x变量,以便在最后一个分配中变为7 ^ 4?

推荐答案

让我们试着展开你的最后一个表达式.

它会评估,

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

请注意,表达式从左到右键,

它变成了,

x = 4 ^ (y = 3 ^ (x = 4 ^ 3));

现在,问题变得明显.右?

编辑:

要清除困惑,让我试着通过从左到右的评估来解释我的意思.

int i = 1;
s = i + (i = 2) + i;

现在,表达式将评估为

s = 1 +    2    + 2;
请注意,左赋值的i 1,但在右侧的分配(并且在挖掘)上被评估为2 ,因为评估从左到右,当它到达表达式的第2和第3部分时,i S值为2.

其他推荐答案

评估顺序在JLS的第15章中定义.项目 15.7.1 说:

如果运算符是复合分配运算符(§15.26.2),则左侧操作数的评估包括记住左侧操作数表示和获取和保存该变量的变量的变量隐含二进制操作.

为了进一步解释,他们有两个涉及分配的计算示例.这里的作业位于运营商的左侧:

int i = 2;
int j = (i=3) * i;
System.out.println(j);

他们具体说结果是9,并且不允许是6.即,(i = 3)都计算为3,并且在乘以自身之前被分配3.

但在第二个例子中:

    int a = 9;
    a += (a = 3);  // first example
    System.out.println(a);
    int b = 9;
    b = b + (b = 3);  // second example
    System.out.println(b);

JLS指定两个打印应该产生12个,并且不允许生成6.即,因为BE的分配位于右侧,左侧b(或隐式左在+=操作中),首先获取和保存该分配之前的值,只执行括号内的操作.

内部,表达式被分解为JVM操作,将其推送和弹出值的"操作数堆栈".如果您认为这样的话 - 在b = b + (b=3)中,首先将b的值推送到操作数堆栈,然后执行(b = 3),然后将其值添加到从堆栈弹出的值( b)的旧值,它会有意义.此时,左手b只是表示"在堆栈上推动b的b值是什么",而不是用于"b"的"当前值".

其他推荐答案

让划分和计算.

最内括号在所有括号中执行的第一个和之后执行,然后表达式从左到右执行.

x ^= (y ^= (x ^= y));   // initial statement

x = x^(y = y^ (x = x^y)); //equals to 

() have the highest precedence

x = x^(y = y^ (x = 3^4)); // first highest precedence () 

x = x^(y = y ^ (x = 7)); // still the first x is 3

x = 4 ^(y = 3 ^ (x = 7));  // now 3 ^ 7 =4

x = 4 ^ 4;  // now  3 ^ 7 =4

x= 0;

本文地址:https://www.itbaoku.cn/post/978707.html