In der Programmiersprache gibt eine Funktion oder Methode im Allgemeinen einen Wert zurück, es gibt jedoch auch Fälle, in denen sie keinen Wert zurückgibt. Derzeit verarbeiten diese Funktionen nur einige Transaktionen und tun dies nicht return, oder mit anderen Worten: Es gibt keinen expliziten Rückgabewert, es verfügt über eine proprietäre Schlüsselwortprozedur in der Pascal-Sprache. In PHP haben Funktionen Rückgabewerte, die in zwei Situationen unterteilt werden können: die Verwendung einer Return-Anweisung zur expliziten Rückgabe und die Rückgabe von NULL ohne Return-Anweisung.
return-Anweisung
Bei Verwendung der return-Anweisung gibt PHP eine Variable des angegebenen Typs an die benutzerdefinierte Funktion zurück. Auf die gleiche Weise, wie wir den Quellcode betrachten, generieren wir nach der lexikalischen Analyse und Syntaxanalyse des Rückgabeschlüsselworts Zwischencode. Aus der Datei Zend/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. Wenn der Rückgabewert ein verwendbarer Ausdruck ist, ist sein Typ der Operationstyp des Ausdrucks, 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) { // 返回引用时不允许常量和临时变量 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)) { // 返回引用 SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr); // is_refgc设置为1 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; // 直接赋值 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 beim Programmstart in *EG(return_value_ptr_ptr) gespeichert wird ausgeführt. Der ZE-Kernel unterscheidet zwischen Wertrückgabe und Referenzrückgabe. Auf dieser Grundlage werden Konstanten, temporäre Variablen und andere Arten von Variablen bei der Rückgabe unterschiedlich behandelt. Bevor die Rückgabe ausgeführt wird, löscht der ZE-Kernel die in der Funktion verwendeten Variablen, indem er die Funktion zend_leave_helper_SPEC aufruft. Dies ist einer der Gründe, warum der ZE-Kernel Funktionen automatisch NULL-Rückgaben hinzufügt.
Funktion ohne Rückgabeanweisung
In PHP gibt es kein Prozedurkonzept, nur Funktionenohne Rückgabewert. Aber für Funktionen, die keinen Rückgabewert haben, „hilft Ihnen“ der PHP-Kernel, einen NULL-Wert als Rückgabewert hinzuzufügen. Dieser „Hilfsvorgang“ wird auch beim Generieren von Zwischencode ausgeführt. Die Funktion zend_do_end_function_declaration muss beim Parsen jeder Funktion ausgeführt werden. In dieser Funktion gibt es eine Anweisung:
zend_do_return(NULL, 0 TSRMLS_CC);
In Kombination mit dem vorherigen Inhalt wissen wir, dass die Funktion dieser Anweisung darin besteht, NULL zurückzugeben. Aus diesem Grund geben Funktionen ohne Return-Anweisung NULL zurück.
Der Rückgabewert der internen Funktion wird über eine Variable namens return_value übergeben. Diese Variable ist auch ein Parameter in der Funktion, der nach der Erweiterung der PHP_FUNCTION-Funktion sichtbar ist. Dieser Parameter enthält immer einen ZVAL-Container mit vorab zugewiesenem Speicherplatz, sodass Sie direkt auf seine Mitglieder zugreifen und sie ändern können, ohne zuerst das Makro MAKE_STD_ZVAL für den Rückgabewert auszuführen. Um die Rückgabe von Ergebnissen aus Funktionen zu erleichtern und den Aufwand des direkten Zugriffs auf die interne Struktur des ZVAL-Containers zu vermeiden, stellt ZEND eine große Menge an Makrobefehlen zum Abschließen dieser zugehörigen Vorgänge bereit. Diese Makros legen Typ und Wert automatisch fest.
Makros, die Werte direkt von Funktionen zurückgeben:
RETURN_RESOURCE(resource) gibt eine Ressource zurück.
RETURN_BOOL(bool) Gibt einen booleschen Wert zurück.
RETURN_NULL() gibt einen Nullwert zurück.
RETURN_LONG(long) Gibt eine lange Ganzzahl zurück.
RETURN_DOUBLE(double) Gibt eine Gleitkommazahl mit doppelter Genauigkeit zurück.
RETURN_STRING(string, duplikat) gibt einen string zurück. Duplikat gibt an, ob dieses Zeichen mit estrdup() kopiert wird.
RETURN_STRINGL(string, length, duplikat) gibt eine Zeichenfolge fester Länge zurück. Der Rest ist derselbe wie bei RETURN_STRING. Dieses Makro ist schneller und binärsicher.
RETURN_EMPTY_STRING() gibt einen leeren String zurück.
RETURN_FALSE Gibt einen booleschen Wert „false“ zurück.
RETURN_TRUE Gibt einen booleschen Wert „true“ zurück.
Makro zum Festlegen des Funktionsrückgabewerts:
RETVAL_RESOURCE(resource) Setzt den Rückgabewert auf eine angegebene Ressource.
RETVAL_BOOL(bool) Setzt den Rückgabewert auf einen angegebenen booleschen Wert.
RETVAL_NULL Setzt den Rückgabewert auf einen Nullwert.
RETVAL_LONG(long) Setzt den Rückgabewert auf eine angegebene lange Ganzzahl.
RETVAL_DOUBLE(double) Setzt den Rückgabewert auf eine angegebene Gleitkommazahl mit doppelter Genauigkeit.
RETVAL_STRING(String, Duplikat) setzt den Rückgabewert auf einen angegebenen String. Die Bedeutung von Duplikat ist dieselbe wie RETURN_STRING.
RETVAL_STRINGL(string, length, duplikat) Setzt den Rückgabewert auf eine angegebene Zeichenfolge fester Länge. Der Rest ist derselbe wie bei RETVAL_STRING. Dieses Makro ist schneller und binärsicher.
RETVAL_EMPTY_STRING setzt den Rückgabewert auf einen leeren String.
RETVAL_FALSE Setzt den Rückgabewert auf Boolean false.
RETVAL_TRUE setzt den Rückgabewert auf Boolean true.
Wenn Sie komplexe Datentypen wie Arrays und Objekte zurückgeben müssen, müssen Sie zuerst array_init () und object_init () aufrufen, oder Sie können die entsprechende Hash-Funktion verwenden, um return_value direkt zu bedienen. Da diese Typen hauptsächlich aus verschiedenen Dingen bestehen, gibt es für sie keine entsprechenden Makros.
Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung zur Verwendung der PHP-Rückgabewert-Rückgabeanweisung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!