字节码模式&&
and ||
想想短路运算符是什么样的&&
or ||
事实上确实如此。你有一些条件分支。让我们考虑一下&&
。您有效评估的是:
if (left)
if (right) <do something>
endIf
没有单个字节码指令可以描述这种行为。您需要一些标签和条件分支指令:
.start
<left expression>
IFEQ .endIf // if left evaluates to zero (false), skip to end
<right expression>
IFEQ .endIf // if right evaluates to zero (false), skip to end
.ifTrue
<body of 'if' block>
.endIf
的行为||
运算符有点不同;在这种情况下,逻辑看起来像这样:
if (left)
goto .ifTrue
if (!right)
goto .endIf
.ifTrue
<do something>
.endIf
请注意如何反转对右操作数的检查,以避免当右操作数计算为时出现额外分支true
。这种行为可以在字节码中实现,如下所示:
<left operand>
IFNE .ifTrue // if left evaluates true, skip right, enter 'if' body
<right operand>
IFEQ .endIf // if right evaluates false, skip 'if' body
.ifTrue
<do something>
.endIf
何时推送操作数
请注意,您最初的问题表明您已经在堆栈上有了左右操作数;那会很糟糕。您应该只评估正确的操作数after左操作数的计算结果为true
(非零)对于&&
or false
(零)对于||
。如果正确的操作数会产生副作用,那么过早地对其求值将违反这些运算符的定义行为。