网站地图    收藏   

主页 > 后端 > php资料库 >

PHP内核研究 函数的参数_自学php网

来源:自学PHP网    时间:2014-12-04 22:12 作者: 阅读:

[导读] 函数的定义只是将函数名注册到函数列表的过程. 下面继续分析函数的参数. 如果没有看就移步到原:PHP内核研究 函数的定义, , function $test($arg=11){ } 还是要看Lex的语法分析 unticked_function...

函数的定义只是将函数名注册到函数列表的过程.
下面继续分析函数的参数.
如果没有看就移步到>>原:PHP内核研究 函数的定义,

,
function $test($arg=11){

}
还是要看Lex的语法分析

unticked_function_declaration_statement:
function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
'(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }

parameter_list 就是分析参数的地方
经过分析找到了解析参数的函数
zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$2, 0 TSRMLS_CC);
这里先要说一下 用来保存函数的结构体zend_arg_info

typedef struct _zend_arg_info {
const char *name; //参数名
zend_uint name_len; //参数名长度
const char *class_name; //参数为类时,指定类名
zend_uint class_name_len;//类名长度
zend_bool array_type_hint;//参数是否是数组
zend_bool allow_null; //参数是否允许为空
zend_bool pass_by_reference; //参数是否为引用 也就是有没有使用&
zend_bool return_reference; //函数自身是否是一个引用函数
int required_num_args; //最少传递几个参数
} zend_arg_info;


zend_do_receive_arg定义在Zend/zend_compile.c中

void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset,

const znode *initialization, znode *class_type, const znode

*varname, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
{
zend_op *opline;
zend_arg_info *cur_arg_info;//声明一个函数结构指针
if (class_type->op_type == IS_CONST && //这里是类相关处理 暂时跳过 讲到类的时候再细说
跳过....
}

if (var->op_type == IS_CV &&
var->u.var == CG(active_op_array)->this_var &&
(CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
} else if (var->op_type == IS_VAR &&
CG(active_op_array)->scope &&
((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
(Z_TYPE(varname->u.constant) == IS_STRING) &&
(Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
(memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")) == 0)) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
}
//创建一个op
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
CG(active_op_array)->num_args++;//参数的个数
opline->opcode = op; //中间码 ZEND_RECV
opline->result = *var;//返回值
opline->op1 = *offset;
if (op == ZEND_RECV_INIT) {
opline->op2 = *initialization;
} else {
CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
SET_UNUSED(opline->op2);
}
//复制参数列表到arr_info
CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
cur_arg_info->name_len = varname->u.constant.value.str.len;
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
cur_arg_info->class_name = NULL;
cur_arg_info->class_name_len = 0;
//这个时候 cur_arg_info->name的值就是 $arg;也就是我们传递过来的参数名
if (class_type->op_type != IS_UNUSED) {//跳过
有略过....
}
opline->result.u.EA.type |= EXT_TYPE_UNUSED;
}

如果函数有N个参数,那么 此函数就会执行N次
下一节将继续介绍 函数的返回值
 

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论