php自訂函數傳回值的深入執行個體詳解

來源:互聯網
上載者:User
函數的傳回值

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返回的原因之一。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.