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
Why does i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j) == 11?
提问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 boolean
values, 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 = 0
for example) evaluates to the value stored (in i
here).
分配(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
:i
is evaluated (0),stuff_1
is evaluated, the bitwise or is taken, and the result stored ini
. Sincei
is originally 0, that is equivalent toi = stuff_1
.j |= stuff_2
:j
is evaluated (2),stuff_2
is evaluated, the bitwise or is taken, and the result is stored inj
.k |= stuff_3
:k
is evaluated (3), thenstuff_3
, left-to-right.(j += i)
addsi
toj
, stores the sum inj
and returnsj
's new value. Sincei
is 0,j
doesn't change and the value is 2.(k++ + k)
takes the old value ofk
(3), incrementsk
and addsk
's new value (4), resulting in 7. That value is negated, and the negated value (-7) subtracted from 2, resulting in2 - (-7) = 9
.(i = +j)
stores the value ofj
(2) ini
and the value of the expression is also 2. The value is negated (-2) and subtracted from the 9 we got from the previous operations, sostuff_3
evaluates to 11, with the side effects that- the stored value of
i
is now 2 - the stored value of
j
is now 2 (didn't actually change, sincei
was 0 initially) - the stored value of
k
is now 4
- the stored value of
- the old value of
k
(3) is bitwise or'ed with 11, resulting in 11, that is stored ink
, and 11 is the value ofstuff_2
, which isk |= stuff_3
.
the old value of
j
(2) is bitwise or'ed with the value ofstuff_2
(11), resulting in 11. The value is stored inj
, and the value ofstuff_1
(j |= stuff_2
) is 11.the old value of
i
(0) is bitwise or'ed with the value ofstuff_1
(11), the result sored ini
, and the value ofi |= stuff_1
is 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)
添加i
到j
,将总和存储在 中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_1
11。然后返回该值。
回答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 i
and j
more than one time between two sequence points.
您的程序在 C 中调用未定义的行为。您在两个序列点之间修改i
和 j
不止一次。
In Java and JavaScript the behavior is well-defined, and you have to look at the precedence and associativity of the operators.
在 Java 和 JavaScript 中,行为是明确定义的,您必须查看运算符的优先级和结合性。