【问题标题】:PHP operator precedence bug?PHP运算符优先级错误?
【发布时间】:2015-10-26 15:39:34
【问题描述】:

结果:

var_dump(null != $a = 15);
var_dump($a);

是:

bool(true)
int(15)

为什么这个脚本没有触发错误? 由于!=(不等于运算符)的优先级高于=(赋值运算符),所以$a应该先与null比较?

【问题讨论】:

  • 确实很奇怪。 $a == null = 15 也提供虚假转储。并且输入(null != $a) = 15 确实会吐出一个意想不到的= 错误。
  • 除了将其解释为 null != ($a=15) 之外,还有什么替代方法?使用(null !=$a)=15,您可以尝试将值 15 分配给布尔值;这行不通。
  • @VolkerK 这是一个例子,这个脚本没有实际用途!我的反思从我经常看到(和使用)的这种表达开始if (!$a = foo())
  • 然后同样的事情也适用。您将如何为 (!$a) 赋值?

标签: php parsing compiler-construction operators


【解决方案1】:

我能找到的唯一原因是文档说这仍然是合法的:http://php.net/manual/en/language.operators.precedence.php#example-129

这似乎是上表中显示的一个例外。

【讨论】:

  • 我认为另一件需要注意的事情是以下关于可读性的评论:“使用括号,即使不是严格必要的,也可以通过显式分组而不是依赖隐式分组来提高代码的可读性运算符优先级和关联性。”
  • 这不是“故意例外”;没有额外的词法分析器规则来明确“允许”这一点。这只是它的正常工作方式。手册中的示例只是对想知道的开发人员的提醒。
  • 但这似乎是页面顶部表格的一个例外,不是吗?即使解析器/词法分析器中没有明确的规则,它似乎是前面解释的一个例外。
  • @VolkerK 调整了我的措辞,你认为现在更正确了吗?
  • 有一个运算符优先级的规则,这个表达式明显违反了规则,这叫做异常。不过没什么大不了的,我继续……
【解决方案2】:

这不是关于运算符优先级,而是关于:运算符优先级列表不会告诉您详细信息(实际上,它们从不告诉您),例如关于野牛规则以及由此产生的模式匹配和堆栈减少。
让我们使用声明 null != $a = 15;,为了简单起见,没有 var_dump。
这就是解析器“看到”这个语句的方式——或者:看到它一个语句。
(我希望这将在任何地方使用固定宽度的字体呈现......)

null                       !=                    $a                                  =   15                           ;
                                                 T_VARIABLE                           
identifier                                       compound_variable                       T_LNUMBER
namespace_name                                   reference_variable                      common_scalar
general_constant                                 base_variable                           scalar
scalar                                           base_variable_with_functions_calls      expr_without_variable
expr_without_variable                            variable                            =   expr
expr                       T_IS_NOT_EQUAL             \______ expr_without_variable _________/
   \__________________    expr ____________________________________________/                                          ;
                           \_________________       unticked_statement _______________________________________________/
                                                     statement                                 

(您可以在https://github.com/php/php-src/blob/PHP-5.6.15/Zend/zend_language_parser.y查看规则)

在这种情况下,赋值运算符没有特殊规则;解析器没有其他方法可以匹配语句,因此优先级不适用。

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    相关资源
    最近更新 更多