【问题标题】:The behaviour of the or operator in PHPPHP 中 or 运算符的行为
【发布时间】:2012-08-26 03:35:51
【问题描述】:

我正在尝试了解or 运算符的行为。请看下面的例子:

$e = false || true;
var_dump($e);

输出如预期:bool(true);

$f = false or true;
var_dump($f);

输出如预期:bool(false)。我的理解是= 的优先级高于Or,所以这就是$f 分配给false 的原因。

但下面的代码与我的想法完全相反。我认为$foo 将分配给5,然后与自身进行比较。 但是 $foo 仅在设置了 $foo 时才被分配,这意味着它正在检查 $foo 是否已分配给之前的任何内容,将 5 分配给它。

$foo or $foo = 5; 

谁能解释为什么会这样?

【问题讨论】:

  • +1 好问题。对于任何坚持这一点的人来说,这对未来的程序员非常有用。
  • 不直接相关,您可能会发现 this page 有用。我也考虑过添加布尔运算符。
  • 我已更新页面以在不同情况下显示“或”和“和”。有一些奇怪的结果。

标签: php or-operator


【解决方案1】:

基础知识:

  1. 赋值表达式产生赋值。

    这是什么意思? $foo = 'bar' 是一个表达式,其中赋值运算符= 赋值。表达式本身总是返回一个值。就像表达式1 + 2 产生值3 一样,表达式$foo = 'bar' 产生值'bar'。这就是它起作用的原因:

    $foo = $bar = 'baz'; // which is: $foo = ($bar = 'baz');
    
  2. 布尔运算是短路运算。如果不需要,双方并不总是被评估。 true || false 总体上总是true,因为左操作数是true,所以整个表达式必须是truefalse 甚至没有在这里进行评估。

  3. Operator precedence 指示表达式的部分按什么顺序分组到子表达式中。高优先级运算符与其操作数在低优先级运算符之前分组。

因此:

$e = false || true;

false || true 正在被评估,这导致值 true,它被分配给 $e|| 运算符的优先级高于 =,因此 false || true 被分组到一个表达式中(而不是 ($e = false) || true)。

$f = false or true;

现在or 的优先级低于=,这意味着赋值操作在or 之前被分组到一个表达式中。所以首先评估$f = false 表达式,其结果是false(见上文)。那么你就有了一个简单的表达式false or true,它接下来会被求值,结果是true,但没人关心。

评估工作如下:

1. $f = false or true;
2. ($f = false) or true;  // precedence grouping
3. false or true;         // evaluation of left side ($f is now false)
4. true;                  // result

现在:

$foo or $foo = 5; 

同样,$foo = 5 具有更高的优先级,并被视为一个表达式。由于它出现在 or 运算符的右侧,因此仅在必要时才计算表达式。这取决于 $foo 最初是什么。如果$footrue,则根本不会评估右侧,因为true or ($foo = 5) 必须是true 整体。如果$foo 最初有一个错误值,则计算右侧并将5 分配给$foo,这导致5,这是真值,这意味着整体表达式是true ,没人关心。

1. $foo or $foo = 5;
2. $foo or ($foo = 5);   // precedence grouping
3. false or ($foo = 5);  // evaluation of left side
4. false or 5;           // evaluation of right side ($foo is now 5)
5. true;                 // result

【讨论】:

  • 第一步就搞定了。谢谢你这么好的解释。仅供参考:我最近从您的charset 主题中受益匪浅。谢谢
  • 看来,当不受 or 等短路运算符的约束时,PHP 确实首先评估带括号的表达式,例如$foo = 2; echo $foo + ($foo = 4) 将打印 8,而不是 6。这实际上是在语言中指定的,还是只是一个实现决定?
  • @Barbar 我相信您可以通过某种方式弄清楚其背后的评估逻辑,但我想说的是,这种自我修改且大多是无意义的操作的行为在定义上大多是未定义的。跨度>
  • @Barmar 没有记录 AFAIK,但这主要不是因为括号,而是因为对于表达式 A + B,PHP 首先计算 A B,然后求和他们起来。现在到了棘手的部分:$foo 计算为相应的 ZVal(变量引用),而 ($foo = 4) 计算为 value 4 并具有修改 $foo 的副作用。 然后他们被总结出来。
  • 你能告诉我什么时候像$b or $b = '1';这样使用,因为如果$b没有设置,它就会上升Undefined variable error
【解决方案2】:

根据php.net webpage about Logical Operators

这个:

$e = false || true;

这样的行为:

$e = (false || true) // If false is true, then $e = false. Otherwise true

这个:

$f = false or true;

会这样:

($f = false) or true; // $f = false is true, as the assignment succeeded

这个:

$foo or $foo = 5; 

会这样:

$foo or ($foo = 5) // foo = undefined or foo = 5, so foo = 5

对于最后一个,undefined 基本上等于 false,因此 foo 等于 5。

另外,这里是运算符优先顺序的链接:http://www.php.net/manual/en/language.operators.precedence.php

更新:

好的,现在让我们进入重点。就像我们都知道使用获取的查询时一样:

while($row = @mysql_fetch_assoc($result))

而且我们都知道 while 循环只在 true 上执行,因此 $row = @mysql_fetch_assoc($result) 返回 true。

与达里克的问题相同。

$foo or $foo = 5;

基本上是:

$foo or ($foo = 5);

基本上是:

$foo = undefined or ($foo = 5); // $foo = 5 actually returns true

这也是

$foo = undefined or true;

正如我之前提到的,undefined = false,因此 $foo = 5(因为这是正确的陈述)。

希望大家能理解。

【讨论】:

  • "如果 $f 不能被赋值,则为真" - 不,而是 如果表达式 $f = false 的结果是 true 或 ... 。而赋值表达式的结果就是赋值。
  • @deceze 我不这么认为。那是根据 PHP 文档。
  • 您可以发布对它的引用吗?不过,没有办法不能分配某些东西,= 运算符总是返回分配的值。
  • @think123 PHP 文档确实指出赋值表达式“返回”赋值结果 php.net/manual/en/language.operators.assignment.php 。这不是“大致相同”,因为$f=true or false 不会“执行”false$f=false or true 将“执行”true
  • @think123: 在这个语句中$foo or $foo = 5; 为什么不首先将5 分配给$foo,因为= 的优先级高于or。为什么不先评估=
【解决方案3】:
$foo or $foo = 5;

Suppose let say $foo=true or $foo=5;

这里它不会在或运算符表达式之后进行评估,因此输出将为 $foo=1 现在表达式是

$foo=false or $foo=5;

在这里,它将在或 as = 更高的优先级之后进行评估,因此 $foo 将评估其中的哪个 $foo=5so 输出将是 5 但是当我们评估 $foo=false or true 时,它会考虑 = 更高的优先级,因此输出将是 $foo=false 但整个表达式将评估为真,因为 false or true 变为 false

【讨论】:

  • 优先级是指分组,而不是评估顺序。正如 deceze 解释的那样,or 总是首先评估其左参数,因为它是一个短路运算符。
【解决方案4】:
<?php
$foo = false;
$foo or ($foo = '5');
echo $foo;
?>

选中此项,您可以为$foo 分配值“5”。

or 相比,= 具有高优先级.. 事实就是如此.... :)

【讨论】:

    猜你喜欢
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 2012-04-27
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 2021-06-20
    相关资源
    最近更新 更多