您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

php自定义函数返回值的深入实例详解

2024/3/22 17:35:28发布22次查看
函数的返回值
php中函数都有返回值,没return返回null
(1)return语句
从zend/zend_language_parser.y文件中可以确认其生成中间代码调用的是zend_do_return函数。
void zend_do_return(znode *expr, int do_end_vparse tsrmls_dc) /* {{{ */ { zend_op *opline; int start_op_number, end_op_number; if (do_end_vparse) { if (cg(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) { zend_do_end_variable_parse(expr, bp_var_w, 0 tsrmls_cc);/* 处理返回引用 */ } else { zend_do_end_variable_parse(expr, bp_var_r, 0 tsrmls_cc);/* 处理常规变量返回 */ } } ...// 省略,取其他中间代码操作 opline->opcode = zend_return; if (expr) { opline->op1 = *expr; if (do_end_vparse && zend_is_function_or_method_call(expr)) { opline->extended_value = zend_returns_function; } } else { opline->op1.op_type = is_const; init_zval(opline->op1.u.constant); } set_unused(opline->op2); } /* }}} */
生成中间代码为zend_return。第一个操作数的类型在返回值为可用的表达式时,其类型为表达式的操作类型,否则类型为is_const。这在后续计算执行中间代码函数时有用到。根据操作数的不同,zend_return中间代码会执行zend_return_spec_const_handler,zend_return_spec_tmp_handler或zend_return_spec_tmp_handler。这三个函数的执行流程基本类似,包括对一些错误的处理。这里我们以zend_return_spec_const_handler为例说明函数返回值的执行过程:
static int zend_fastcall zend_return_spec_const_handler(zend_opcode_handler_args) { zend_op *opline = ex(opline); zval *retval_ptr; zval **retval_ptr_ptr; if (eg(active_op_array)->return_reference == zend_return_ref) { // ǔǔŷsá\ɂƶmļ@ɗáļļ if (is_const == is_const || is_const == is_tmp_var) { /* not supposed to happen, but we'll allow it */ zend_error(e_notice, "only variable references \ should be returned by reference"); goto return_by_value; } retval_ptr_ptr = null; // ǔǔŕ if (is_const == is_var && !retval_ptr_ptr) { zend_error_noreturn(e_error, "cannot return string offsets by reference"); } if (is_const == is_var && !z_isref_pp(retval_ptr_ptr)) { if (opline->extended_value == zend_returns_function && ex_t(opline->op1.u.var).var.fcall_returned_reference) { } else if (ex_t(opline->op1.u.var).var.ptr_ptr == &ex_t(opline->op1.u.var).var.ptr) { if (is_const == is_var && !0) { /* undo the effect of get_zval_ptr_ptr() */ pzval_lock(*retval_ptr_ptr); } zend_error(e_notice, "only variable references \ should be returned by reference"); goto return_by_value; } } if (eg(return_value_ptr_ptr)) { // ǔǔŷs separate_zval_to_make_is_ref(retval_ptr_ptr); // is_refgcőęŒ z_addref_pp(retval_ptr_ptr); // refcountgcœď×1 (*eg(return_value_ptr_ptr)) = (*retval_ptr_ptr); } } else { return_by_value: retval_ptr = &opline->op1.u.constant; if (!eg(return_value_ptr_ptr)) { if (is_const == is_tmp_var) { } } else if (!0) { /* not a temp var */ if (is_const == is_const || eg(active_op_array)->return_reference == zend_return_ref || (pzval_is_ref(retval_ptr) && z_refcount_p(retval_ptr) > 0)) { zval *ret; alloc_zval(ret); init_pzval_copy(ret, retval_ptr); // ł™Ϳʍǔǔŕ zval_copy_ctor(ret); *eg(return_value_ptr_ptr) = ret; } else { *eg(return_value_ptr_ptr) = retval_ptr; // ħ6ɶŕ z_addref_p(retval_ptr); } } else { zval *ret; alloc_zval(ret); init_pzval_copy(ret, retval_ptr); // ł™Ϳʍǔǔŕ *eg(return_value_ptr_ptr) = ret; } } return zend_leave_helper_spec(zend_opcode_handler_args_passthru); // ǔ ǔĉˆșʒ }
函数的返回值在程序执行时存储在*eg(return_value_ptr_ptr)。zend内核对值返回和引用返回作了区别,并且在此基础上对常量,临时变量和其他类型的变量在返回时作了不同的处理。在return执行完之后,zend内核通过调用zend_leave_helper_spec函数,清除函数内部使用的变量等。这也是zend内核自动给函数加上null返回的原因之一。
以上就是php自定义函数返回值的深入实例详解的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product