gpt4 book ai didi

php - 括号改变函数调用结果的语义

转载 作者:IT王子 更新时间:2023-10-29 00:39:31 26 4
gpt4 key购买 nike

another question 中注明将 PHP 函数调用的结果包装在括号中可以以某种方式将结果转换为成熟的表达式,这样以下工作就可以了:

<?php
error_reporting(E_ALL | E_STRICT);

function get_array() {
return array();
}

function foo() {
// return reset(get_array());
// ^ error: "Only variables should be passed by reference"

return reset((get_array()));
// ^ OK
}

foo();

我试图在文档中找到任何内容以明确并明确地解释这里发生的事情。与 C++ 不同,我对 PHP 语法及其对语句/表达式的处理知之甚少,无法自己派生它。

文档中是否隐藏了有关此行为的任何内容?如果不是,是否有其他人可以解释而不诉诸假设?


更新

我第一次发现 this EBNF声称代表PHP语法,并试图自己解码我的脚本,但最终放弃了。

然后,using phc要生成两个 foo() 变体的 .dot 文件,我 produced使用以下命令为这两个脚本提供 AST 图像:

$ yum install phc graphviz
$ phc --dump-ast-dot test1.php > test1.dot
$ dot -Tpng test1.dot > test1.png
$ phc --dump-ast-dot test2.php > test2.dot
$ dot -Tpng test2.dot > test2.png

在这两种情况下,结果完全相同:

Parse tree of snippets 1 and 2

最佳答案

此行为可归类为错误,因此您绝对不应依赖它。

在函数调用中 抛出消息的(简化)条件如下(参见 definition of the opcode ZEND_SEND_VAR_NO_REF ):

  • 参数不是函数调用(或者如果是,它通过引用返回),并且
  • 参数要么是一个引用,要么它的引用计数为 1(如果它的引用计数为 1,则它变成了一个引用)。

让我们更详细地分析一下。

第一点是正确的(不是函数调用)

由于额外的括号,PHP 不再检测到参数是函数调用。

解析 non empty function argument list 时PHP 有以下三种可能性:

  • 一个expr_without_variable
  • 一个变量
  • (一个 & 后跟一个 变量,用于删除调用时间传递引用功能)

当只写 get_array() 时,PHP 将其视为一个变量

另一方面,

(get_array()) 不符合变量 的条件。它是一个 expr_without_variable

这最终会影响代码的编译方式,即操作码SEND_VAR_NO_REF的扩展值将不再包含标志ZEND_ARG_SEND_FUNCTION,这是函数调用的方式在操作码实现中检测到。

第二点为真(引用计数为1)

在几个点上,Zend 引擎允许在需要引用的地方使用引用计数为 1 的非引用。这些细节不应该暴露给用户,但不幸的是,它们就在这里。

在您的示例中,您将返回一个未从其他任何地方引用的数组。如果是,您仍然会收到消息,即第二点不正确。

所以下面非常相似的例子不起作用:

<?php

$a = array();
function get_array() {
return $GLOBALS['a'];
}

return reset((get_array()));

关于php - 括号改变函数调用结果的语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6726589/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com