Funktionen in PHP haben alle Rückgabewerte und keine Rückgabe gibt null zurück
(1) Rückgabeanweisung
Von Zend In der Datei /zend_lingual_parser.y kann bestätigt werden, dass der generierte Zwischencode die Funktion zend_do_return aufruft.
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); } /* }}} */
Der generierte Zwischencode ist ZEND_RETURN. Der Typ des ersten Operanden ist der Operationstyp des Ausdrucks, wenn der Rückgabewert ein verwendbarer -Ausdruck ist, andernfalls ist der Typ IS_CONST. Dies ist nützlich, wenn nachfolgende Berechnungen Zwischencodefunktionen ausführen. Abhängig von den Operanden führt der ZEND_RETURN-Zwischencode ZEND_RETURN_SPEC_CONST_HANDLER, ZEND_RETURN_SPEC_TMP_HANDLER oder ZEND_RETURN_SPEC_TMP_HANDLER aus. Die Ausführungsabläufe dieser drei Funktionen sind grundsätzlich ähnlich, einschließlich der Behandlung einiger Fehler. Hier nehmen wir ZEND_RETURN_SPEC_CONST_HANDLER als Beispiel, um den Ausführungsprozess des Funktionsrückgabewerts zu veranschaulichen:
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); // Ǔ ǔĉșʒ }
Der Rückgabewert der Funktion wird in *EG(return_value_ptr_ptr) gespeichert, wenn das Programm ausgeführt wird. Der ZEND-Kernel unterscheidet zwischen Wertrückgabe und Referenzrückgabe und auf dieser Grundlage werden Konstanten, temporäre Variablen und andere Variablentypen bei der Rückgabe unterschiedlich behandelt. Nachdem return ausgeführt wurde, löscht der ZEND-Kernel die in der Funktion verwendeten Variablen, indem er die Funktion zend_leave_helper_SPEC aufruft. Dies ist einer der Gründe, warum der ZEND-Kernel Funktionen automatisch NULL-Rückgaben hinzufügt.
Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung ausführlicher Beispiele für Rückgabewerte benutzerdefinierter PHP-Funktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!