java 为什么 i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j) == 11?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13519990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:04:47  来源:igfitidea点击:

Why does i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j) == 11?

javaoperatorsoperator-precedence

提问by Facebook Staff are Complicit

I came across this code in a project I have started working on. The original developer is no longer available, and I can't make any sense of it:

我在我开始工作的一个项目中遇到了这段代码。原来的开发者不再可用,我无法理解:

k = (j = (i = 0) + 2) + 1;
return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);

It produces a value of 11. How does this work?

它产生的值为11。这是如何运作的?

What is the =+operator?

=+运营商是什么?

What is the +++operator?

+++运营商是什么?

What is the - -operator?

- -运营商是什么?

What is the |=operator?

|=运营商是什么?

回答by Daniel Fischer

What is the =+operator?

=+运营商是什么?

That's two operators, one assignment operator, =, and one unary plus, +, which does nothing.

那是两个运算符,一个赋值运算符 ,=和一个一元加号+,它什么都不做。

Did you typo and mean the compund assignment operator +=?

你打错字了吗,意思是复合赋值运算符+=

What is the +++operator?

+++运营商是什么?

Also two operators, one post-increment, ++, and one addition, +, (per the maximal munch rule, the longest valid token is chosen, it would become one addition and two unary plus if the shortest valid token were chosen).

还有两个运算符,一个后增量,++和一个加法,+,(根据最大蒙克规则,选择最长的有效标记,如果选择最短的有效标记,它将成为一个加法和两个一元加)。

What is the - -operator?

- -运营商是什么?

Again two operators, one subtraction, and one unary minus (negation).

同样是两个运算符,一个减法,一个一元减号(否定)。

What is the |=operator?

|=运营商是什么?

A compound assignment, bitwise-oring [or, in the case of booleanvalues, logical-oring] the left-hand-side value with the right-hand-side value and storing that in the left-hand-side variable.

复合赋值,按位或运算 [或,在boolean值的情况下,逻辑或运算] 左侧值与右侧值并将其存储在左侧变量中。

a |= b;

is nearly equivalent to

几乎相当于

a = a | b;

but the left-hand-side operand is evaluated only once, and the latter may need an explicit cast where the former doesn't.

但左侧操作数只计算一次,后者可能需要显式转换,而前者不需要。

k = (j = (i = 0) + 2) + 1;
return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);

It produces a value of 11. How does this work?

它产生的值为 11。这是如何工作的?

The first line is equivalent to

第一行相当于

i = 0;
j = i+2;
k = j+1;

The assignment (i = 0for example) evaluates to the value stored (in ihere).

分配(i = 0例如)评估为存储的值(在i此处)。

The next line is, with proper spacing, and implicit parentheses added

下一行是适当的间距,并添加了隐式括号

return i |= (j |= (k |= (((j += i) - (-(k++ + k))) - (-(i = +j)))));
  • i |= stuff_1: iis evaluated (0), stuff_1is evaluated, the bitwise or is taken, and the result stored in i. Since iis originally 0, that is equivalent to i = stuff_1.

  • j |= stuff_2: jis evaluated (2), stuff_2is evaluated, the bitwise or is taken, and the result is stored in j.

  • k |= stuff_3: kis evaluated (3), then stuff_3, left-to-right.

    • (j += i)adds ito j, stores the sum in jand returns j's new value. Since iis 0, jdoesn't change and the value is 2.
    • (k++ + k)takes the old value of k(3), increments kand adds k's new value (4), resulting in 7. That value is negated, and the negated value (-7) subtracted from 2, resulting in 2 - (-7) = 9.
    • (i = +j)stores the value of j(2) in iand the value of the expression is also 2. The value is negated (-2) and subtracted from the 9 we got from the previous operations, so stuff_3evaluates to 11, with the side effects that

      • the stored value of iis now 2
      • the stored value of jis now 2 (didn't actually change, since iwas 0 initially)
      • the stored value of kis now 4
    • the old value of k(3) is bitwise or'ed with 11, resulting in 11, that is stored in k, and 11 is the value of stuff_2, which is k |= stuff_3.
  • the old value of j(2) is bitwise or'ed with the value of stuff_2(11), resulting in 11. The value is stored in j, and the value of stuff_1(j |= stuff_2) is 11.

  • the old value of i(0) is bitwise or'ed with the value of stuff_1(11), the result sored in i, and the value of i |= stuff_1is 11. That value is then returned.

  • i |= stuff_1:i被求值 (0),stuff_1被求值,按位取或,结果存入i. 由于i最初为 0,因此相当于i = stuff_1

  • j |= stuff_2:j被求值 (2),stuff_2被求值,按位取或,结果存入j.

  • k |= stuff_3:k被评估 (3),然后stuff_3,从左到右。

    • (j += i)添加ij,将总和存储在 中j并返回j的新值。因为i是 0,j所以不会改变,值为 2。
    • (k++ + k)k(3)的旧值,递增k并添加k的新值 (4),结果为 7。该值被取反,取反值 (-7) 从 2 中减去,结果为2 - (-7) = 9
    • (i = +j)j(2)的值存储在i,表达式的值也是 2。该值被取反 (-2) 并从我们从前面的操作中得到的 9 中减去,因此stuff_3计算结果为 11,副作用是

      • 的存储值i现在是 2
      • 的存储值j现在是 2(实际上没有改变,因为i最初是 0)
      • 的存储值k现在是 4
    • k(3)的旧值与 11 进行按位或运算,结果为 11,即存储在 中k,而 11 是 的值stuff_2,即k |= stuff_3
  • j(2)的旧值与stuff_2(11)的值进行按位或运算,结果为 11。该值存储在 中j,并且stuff_1( j |= stuff_2) 的值为 11。

  • i(0)的旧值与stuff_1(11)的值进行按位或运算,结果存入i,并且 的值为i |= stuff_111。然后返回该值。

回答by Glen Best

The original developer is no longer available, and I can't make any sense of it.

原来的开发者不再可用,我无法理解。

The original developer has deliberately left a torturous assignment question in the code. This is exactly the same answer given by Daniel Fischer, but to clearly explain, I'll evaluate in steps corresponding to the evaluation order.

原开发者故意在代码中留下了一个折磨人的赋值问题。这与 Daniel Fischer 给出的答案完全相同,但为了清楚地解释,我将按照与评估顺序相对应的步骤进行评估。

k = (j = (i = 0) + 2) + 1;

k = (j = (i = 0) + 2) + 1;

With parenthesis & operator precedence, is evaluated as:

使用括号和运算符优先级,计算为:

i = 0;    
j = i + 2;  // j = 2
k = j + 1;  // k = 3

return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);

返回 i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);

Expanding the "|=" operators, this is equivalent to:

展开“|=”运算符,这相当于:

return i = i | ( j = j | ( k = k | ( (j+= i) - - (k+++k) - - (i =+j) ) ) );

Left of "|" operator is always evaluated first and remembered, so substituting variable values into left side:

“|”的左边 运算符总是首先计算并记住,因此将变量值代入左侧:

return i = 0 | ( j = 2 | ( k = 3 | ( (j+= i) - - (k+++k) - - (i =+j) ) ) );

Then evaluating right side of each "|" operator (with parenthesis, operator and left-to-right precedence):

然后评估每个“|”的右侧 运算符(带括号、运算符和从左到右的优先级):

(j+= i):   pre-increments j = j + i;            //  j = 2 + 0 = 2
           then expression evaluates to j       //  evaluates to 2                   

(k+++k):   first evaluates k++                  //  sub-expression evaluates to 3, 
                                                //  then post-increments k: k = 4 
           then evaluates (k++)+k               //  evaluates to 3+4 = 7

(i =+ j):  "=+" is not an java operator!!
           it is evaluated as "=" operator followed by unary "+" operator
           expression evaluates to +j           // evaluates to 2

k = 3 | ( (j+= i) - - (k+++k) - - (i =+j) )
  = 3 | ( 2 - -7 - -2) = 3 | 11 = (2+1) | (8+2+1) = (8+2+1) = 11


j = 2 | k
  = 2 | 11 = (2) | (8+2+1) = 8+2+1 = 11


i = 1 | j;                    
  = 1 | 11 = (1) | (8+2+1) = 8+2+1 = 11

return i;  // return 11

回答by Steph

To me, the best answer is Mike Rylander's (in comment).

对我来说,最好的答案是 Mike Rylander 的(评论中)。

Replace it with return 11;and commit.

将其替换为return 11;并提交。

I mean, the code is not dependent on anything written before, so it produces 11 everytime. It is a complex computation that takes time for nothingand produces 11. So you just have to return 11. Do not keep the useless code of a developper who was obviously having fun on you. It reminds me of a former colleague, who set a bomb in the code (something that seldom crashes, but sometimes crashes indeed), just before resigning...

我的意思是,该代码不依赖于之前编写的任何内容,因此每次都会生成 11。这是一个复杂的计算,需要时间白白并产生11所以你就必须回到11不要让谁显然有你乐趣developper的无用的代码。这让我想起了一位前同事,在辞职之前,他在代码中设置了炸弹(很少崩溃,但有时确实会崩溃)...

Note :There might be a case where it is not equivalent: if i, j, and k are visible outside your method and reused somewhere else. But it is highly unlikely.

注意:可能存在不等价的情况:如果 i、j 和 k 在您的方法之外可见并在其他地方重用。但这是极不可能的。

回答by ouah

Your program invokes undefined behavior in C. You are modifying iand jmore than one time between two sequence points.

您的程序在 C 中调用未定义的行为。您在两个序列点之间修改ij不止一次。

In Java and JavaScript the behavior is well-defined, and you have to look at the precedence and associativity of the operators.

在 Java 和 JavaScript 中,行为是明确定义的,您必须查看运算符的优先级和结合性。