函数参数

3.2.1.2 函数参数

函数参数在内核实现上与函数内的局部变量实际是一样的,上一篇我们介绍编译的时候提供局部变量会有一个单独的 编号 ,而函数的参数与之相同,参数名称也在zend_op_array.vars中,编号首先是从参数开始的,所以按照参数顺序其编号依次为0、1、2...(转化为相对内存偏移量就是96、112、128...),然后函数调用时首先会在调用位置将参数的value复制到各参数各自的位置,详细的传参过程我们在执行一篇再作说明。

比如:

function my_function($a, $b = "aa"){
    $ret = $a . $b;
    return $ret;
}

编译完后各变量的内存偏移量编号:

$a   => 96
$b   => 112
$ret => 128

与下面这么写一样:

function my_function(){
    $a = NULL;
    $b = "aa";
    $ret = $a . $b;
    return $ret;
}

另外参数还有其它的信息,这些信息通过zend_arg_info结构记录:

typedef struct _zend_arg_info {
    zend_string *name; //参数名
    zend_string *class_name;
    zend_uchar type_hint; //显式声明的参数类型,比如(array $param_1)
    zend_uchar pass_by_reference; //是否引用传参,参数前加&的这个值就是1
    zend_bool allow_null; //是否允许为NULL,注意:这个值并不是用来表示参数是否为必传的
    zend_bool is_variadic; //是否为可变参数,即...用法,与golang的用法相同,5.6以上新增的一个用法:function my_func($a, ...$b){...}
} zend_arg_info;

每个参数都有一个上面的结构,所有参数的结构保存在zend_op_array.arg_info数组中,这里有一个地方需要注意:zend_op_array->arg_info数组保存的并不全是输入参数,如果函数声明了返回值类型则也会为它创建一个zend_arg_info,这个结构在arg_info数组的第一个位置,这种情况下zend_op_array->arg_info指向的实际是数组的第二个位置,返回值的结构通过zend_op_array->arg_info[-1]读取,这里先单独看下编译时的处理:

//函数参数的编译
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast)
{
    zend_ast_list *list = zend_ast_get_list(ast);
    uint32_t i;
    zend_op_array *op_array = CG(active_op_array);
    zend_arg_info *arg_infos;

    if (return_type_ast) {
        //声明了返回值类型:function my_func():array{...}
        //多分配一个zend_arg_info
        arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
        ...
        arg_infos->allow_null = 0;
        ...
        //arg_infos指向了下一个位置
        arg_infos++;
        op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
    } else {
        //没有声明返回值类型
        if (list->children == 0) {
            return;
        }
        arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
    }
    ...

    op_array->num_args = list->children;
    //声明了返回值的情况下arg_infos已经指向了数组的第二个元素
    op_array->arg_info = arg_infos;
}
联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3