-80 java operators operator-precedence
我在一个我开始研究的项目中遇到了这段代码.最初的开发人员已经不再可用,我无法理解它.
k = (j = (i = 0) + 2) + 1;
return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);
Run Code Online (Sandbox Code Playgroud)
它产生的价值11.这是如何运作的?
什么是=+运营商?
什么是+++运营商?
什么是- -运营商?
什么是|=运营商?
Dan*_*her 202
什么是
=+运营商?
这是两个运算符,一个赋值运算符,=一个一元加号+,它什么都不做.
你错了并且意味着compund赋值运算符+=?
什么是
+++运营商?
还有两个运算符,一个后增量,++一个加法,+(根据最大蒙克规则,选择最长的有效令牌,如果选择了最短的有效令牌,它将成为一个加法和两个一元加号).
什么是
- -运营商?
再两个运算符,一个减法和一个一元减(否定).
什么是
|=运营商?
复合赋值,按位[或者,在boolean值的情况下,逻辑运算]左侧值与右侧值并将其存储在左侧变量中.
a |= b;
Run Code Online (Sandbox Code Playgroud)
几乎相当于
a = a | b;
Run Code Online (Sandbox Code Playgroud)
但是左侧操作数只被评估一次,后者可能需要一个显式的强制转换,而前者则不需要.
k = (j = (i = 0) + 2) + 1;
return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);
Run Code Online (Sandbox Code Playgroud)
它产生的值为11.这是如何工作的?
第一行相当于
i = 0;
j = i+2;
k = j+1;
Run Code Online (Sandbox Code Playgroud)
赋值(i = 0例如)计算存储的值(在i此处).
下一行是适当的间距,并添加了隐式括号
return i |= (j |= (k |= (((j += i) - (-(k++ + k))) - (-(i = +j)))));
Run Code Online (Sandbox Code Playgroud)
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现在存储的值为2j现在存储的值是2(实际上没有变化,因为i最初为0)k现在存储的值是4k(3)的旧值按位或按11,得到11,存储在k11 中,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.然后返回该值.
Gle*_*est 45
最初的开发人员已经不再可用,我无法理解它.
最初的开发人员故意在代码中留下了一个曲折的任务问题.这与Daniel Fischer给出的答案完全相同,但为了清楚地解释,我将按照与评估顺序相对应的步骤进行评估.
k =(j =(i = 0)+ 2)+ 1;
括号和运算符优先级,评估为:
i = 0;
j = i + 2; // j = 2
k = j + 1; // k = 3
Run Code Online (Sandbox Code Playgroud)
return i | = j | = k | =(j + = i) - - (k +++ k) - - (i = + j);
扩展"| ="运算符,这相当于:
return i = i | ( j = j | ( k = k | ( (j+= i) - - (k+++k) - - (i =+j) ) ) );
Run Code Online (Sandbox Code Playgroud)
左边的"|" 始终首先评估运算符并记住,因此将变量值替换为左侧:
return i = 0 | ( j = 2 | ( k = 3 | ( (j+= i) - - (k+++k) - - (i =+j) ) ) );
Run Code Online (Sandbox Code Playgroud)
然后评估每个"|"的右侧 运算符(带括号,运算符和从左到右的优先级):
(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
Run Code Online (Sandbox Code Playgroud)
Ste*_*eph 18
对我来说,最好的答案是Mike Rylander(评论中).
用它替换
return 11;并提交.
我的意思是,代码不依赖于之前编写的任何内容,因此每次生成11.这是一个复杂的计算,需要时间,什么都不会产生11.所以你只需要返回11.不要保持开发者的无用代码显然对你很开心.它让我想起了一位前同事,他在代码中设置了炸弹(很少崩溃,但有时甚至崩溃),就在辞职之前......
注意:可能存在不等效的情况:如果i,j和k在方法之外可见并在其他地方重复使用.但这不太可能.
oua*_*uah 15
你的程序中调用C.要修改不确定的行为i和 j两个控制顺序点之间超过一次.
在Java和JavaScript中,行为是明确定义的,您必须查看运算符的优先级和关联性.