40

在 PHP 代码中

if(a() && b())

当第一个操作数计算为 时falseb()将不计算。

同样,在

if (a() || b())

当第一个操作数计算为 时trueb()将不计算..

这适用于所有语言,如 Java、C# 等吗?

这是我们使用的测试代码。

<?php
function a(){
echo 'a';
return false;
}

function b(){
echo 'b';
return true;
}


if(a() && b()){
echo 'c';
}
?>
4

17 回答 17

68

这称为短路评估

对于从 C 派生的语言(C、C++、Java、C#)通常是正确的,但并非对所有语言都是正确的。

例如,VB6 不这样做,在早期版本的 VB.NET 中也没有这样做。VB8(在 Visual Studio 2005 中)为此目的引入了AndAlsoOrElse运算符。

此外,从评论来看,似乎 csh 从右到左执行短路评估,使事情变得更加混乱。

还应该指出,短路评估(或缺乏)有其危险需要注意。例如,如果第二个操作数是具有任何副作用的函数,则代码可能无法完全按照程序员的预期执行。

于 2009-08-05T11:19:15.207 回答
20

VB6 并非如此。

在 VB.net 中,如果您希望它跳过评估第二个表达式,则必须使用“AndAlso”而不是“And”。

于 2009-08-05T11:18:19.703 回答
12

这称为短路评估,大多数语言都这样做。在某些语言中,存在不这样做的运算符。

于 2009-08-05T11:19:18.843 回答
12

这适用于所有语言,如 JAVA、C# 等吗?

在 C# 中,这仅适用于短路运算符 ' ||' 和 ' &&';如果您只使用 ' |' 或 ' &' 它每次都会评估双方。

于 2009-08-05T11:24:09.800 回答
8

Pascal的原始版本没有,这引起了很多悲伤。现代 Pascals,如 Delphi,与 C 等人的工作方式相同。

于 2009-08-05T11:21:08.887 回答
7

Ada 有特殊的短路形式的条件句:

and then
or else

像这样使用:

if p.next /= null and then p.next.name = 'foo'
if x = 0 or else 1/x = y

在某些方面它有点好,因为你可以推断出程序员知道表达式需要被短路并且条件不是偶然的。

于 2009-08-05T11:30:54.607 回答
5

对于作为 C 的“子代”的语言来说是这样的:PHP、Java、C++、C#……或者在相同的“灵感”中,比如 Perl。

但对于 VB 来说并非如此(至少在 .NET 之前,它为此引入了新的关键字)。
(第一次使用 VB 时,这真的很令人不安 ^^)

于 2009-08-05T11:20:42.973 回答
4

Microsoft VBScript(通常与“经典”ASP 结合使用)对布尔运算符没有短路求值,而是使用按位求值。这是它可能是有史以来最糟糕的语言的众多原因之一!

“发生的事情是 VBScript 不是逻辑的。VBScript 是按位的。所有所谓的逻辑运算符都适用于数字,而不是布尔值!Not、And、Or、XOr、Eqv 和 Imp 都将它们的参数转换为四字节整数,对整数中的每一对位进行逻辑运算,并返回结果。如果 True 为 -1 并且 False 为 0 则一切正常,因为 -1 的所有位都打开,0 的所有位都打开关闭。但如果其他数字进入那里,所有的赌注都被关闭“。

取自这个博客。埃里克·利珀特。

于 2009-08-05T12:59:37.587 回答
3

在 Delphi 中,它是一个编译器选项。

于 2009-08-05T12:53:17.120 回答
3

在标准 FORTRAN 或 Fortran 中,布尔表达式的操作数可以按任何顺序计算。允许不完整的评估,但定义了实现。

这允许优化布尔表达式,如果强制执行严格的从左到右排序,则不允许这样做。需要严格排序的表达式必须分解为单独的条件,或者可以做出依赖于实现的假设。

由于分解用于强制排序,因此不能始终将单独的 IF 语句优化为单个表达式。然而,短路评估在分解中是显式的,这永远不会比强制严格从左到右排序以允许惰性评估的语言更糟糕。

源自 FORTRAN 的语言(Fortran、BASIC、VBn)和旨在实现类似 FORTRAN 的效率的语言(Pascal、Ada)最初遵循允许无序评估的 FORTRAN 示例。

于 2015-03-17T11:24:47.413 回答
2

对于 Java 也是如此,但运算符 | 和 & 等将评估双方。

于 2009-08-05T11:22:45.543 回答
2

这称为短路评估,它对我曾经使用过的所有语言(C、C++、C#、Java、Smalltalk、Javascript、Lisp)都很常见,除了 VB、VB.NET 和 Fortran。

这实际上是一个非常有用的功能。如果没有短路,您将无法做到这一点:

if (a != null && a.isBlank())

如果没有短路,您将不得不嵌套 if 语句,因为如果 a 为空,第二部分将引发错误。

于 2009-08-05T11:30:47.150 回答
2

大多数语言(我见过的所有语言)都对条件运算符(例如 && 和 ||)使用短路求值。只要其中一个条件满足要求,他们就会停止评估。(&& 上的第一个假。|| 上的第一个真)

处理所有 BINARY 运算符,例如 & 和 |。(原来的)

处理所有 BITWISE 运算符,例如 & 和 |。(编辑:2017 年 5 月 10 日)

于 2009-08-05T12:01:46.823 回答
2

在 Erlang 中,andandor运算符不做短路求值;如果您想要短路行为,则必须使用orelseand运算符。andalso

于 2009-08-05T13:59:22.193 回答
1

Coldfusion 本身会进行短路评估。我相信所有 CF 开发人员都写过:

<cfif isdefined("somevariable") and somevariable eq something>
//do logic
</cfif>
于 2009-08-05T11:33:33.043 回答
1

MATLAB 是一种区分“标准”逻辑运算符短路运算符的语言:

  • &(AND 运算符)和 | (OR 运算符)可以按元素方式对数组进行操作。
  • && 和 || 是短路版本,仅当结果未完全由第一个操作数确定时才计算第二个操作数。这些只能在标量上操作,而不是数组。
于 2009-08-05T14:22:23.567 回答
0

其他答案已经给出了有和没有短路评估的语言的很好的例子,所以我不会重复它们。

只需添加一个有趣的点:诸如 Clojure 之类的 Lisps 具有布尔短路评估,但此外,您可以通过使用宏非常简单地定义任何您喜欢的短路评估运算符。

Clojure 中的短路“nand”操作示例:

(defmacro nand 
  ([x] 
    `(not ~x))
  ([x & xs] 
    `(let [nand# (not ~x)]
       (if nand# 
         true               ; short circuit if we can prove the nand is true
         (nand ~@xs)))))    ; continue with the other expressions otherwise

(nand true true)
=> false

(nand false (println "Expression with a side effect!"))
=> true
于 2011-11-19T08:55:32.593 回答