括号会改变函数调用结果的语义 [英] Parentheses altering semantics of function call result

查看:86
本文介绍了括号会改变函数调用结果的语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个问题中指出,将PHP函数调用的结果括在括号中可以以某种方式将结果转换为完整的表达式,以便进行以下工作:

It was noted in another question that wrapping the result of a PHP function call in parentheses can somehow convert the result into a fully-fledged expression, such that the following works:

<?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语法及其对语句/表达式的处理知之甚少.

I'm trying to find anything in the documentation to explicitly and unambiguously explain what is happening here. Unlike in C++, I don't know enough about the PHP grammar and its treatment of statements/expressions to derive it myself.

文档中是否存在与此行为有关的任何隐藏内容?如果不是,那么其他人可以在不诉诸假设的情况下进行解释吗?

Is there anything hidden in the documentation regarding this behaviour? If not, can somebody else explain it without resorting to supposition?

我首先发现此EBNF 旨在代表PHP语法,并尝试自己解码我的脚本,但最终放弃了.

I first found this EBNF purporting to represent the PHP grammar, and tried to decode my scripts myself, but eventually gave up.

然后使用phc 生成一个两个foo()变体的.dot文件,我生成使用以下命令对两个脚本的AST图像:

Then, using phc to generate a .dot file of the two foo() variants, I produced AST images for both scripts using the following commands:

$ 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

在两种情况下,结果都是完全相同的:

In both cases the result was exactly the same:

推荐答案

此行为可以归类为 bug ,因此您绝对不应依赖它.

This behavior could be classified as bug, so you should definitely not rely on it.

要在函数调用上抛出 not 消息的(简化)条件如下(请参阅

The (simplified) conditions for the message not to be thrown on a function call are as follows (see the definition of the opcode ZEND_SEND_VAR_NO_REF):

  • 该参数不是函数调用(如果是,则通过引用返回),并且
  • 该参数可以是引用,也可以具有引用计数1(如果引用引用为1,则将其转换为引用).
  • the argument is not a function call (or if it is, it returns by reference), and
  • the argument is either a reference or it has reference count 1 (if it has reference count 1, it's turned into a reference).

让我们更详细地分析它们.

Let's analyze these in more detail.

由于附加了括号,PHP不再检测到该参数是函数调用.

Due to the additional parentheses, PHP no longer detects that the argument is a function call.

当解析非空函数参数列表时,有PHP的三种可能性:

When parsing a non empty function argument list there are three possibilities for PHP:

  • 一个expr_without_variable
  • A variable
  • (删除引用的呼叫时传递功能的&后跟variable)
  • An expr_without_variable
  • A variable
  • (A & followed by a variable, for the removed call-time pass by reference feature)

仅编写get_array()时,PHP会将其视为variable.

When writing just get_array() PHP sees this as a variable.

(get_array())不符合variable的条件.这是expr_without_variable.

(get_array()) on the other hand does not qualify as a variable. It is an expr_without_variable.

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

This ultimately affects the way the code compiles, namely the extended value of the opcode SEND_VAR_NO_REF will no longer include the flag ZEND_ARG_SEND_FUNCTION, which is the way the function call is detected in the opcode implementation.

在某些情况下,Zend Engine允许引用计数为1的非引用(需要引用).这些细节不应该向用户公开,但是不幸的是,它们在这里.

At several points, the Zend Engine allows non-references with reference count 1 where references are expected. These details should not be exposed to the user, but unfortunately they are here.

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

In your example you're returning an array that's not referenced from anywhere else. If it were, you would still get the message, i.e. this second point would not be true.

因此以下非常相似的示例不起作用 :

So the following very similar example does not work:

<?php

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

return reset((get_array()));

这篇关于括号会改变函数调用结果的语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆