>  기사  >  백엔드 개발  >  PHP 사용자 정의 함수 반환 값의 심층적인 예에 ​​대한 자세한 설명

PHP 사용자 정의 함수 반환 값의 심층적인 예에 ​​대한 자세한 설명

伊谢尔伦
伊谢尔伦원래의
2017-06-26 13:32:031209검색

함수의 반환값

PHP의 함수는 모두 반환값을 가지며, 반환값은 null을 반환하지 않습니다.

(1) 반환문

Zend/zend_언어_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입니다. 첫 번째 피연산자의 유형은 반환 값이 사용 가능한 expression인 경우 표현식의 연산 유형이고, 그렇지 않은 경우 유형은 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 사용자 정의 함수 반환 값의 심층적인 예에 ​​대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.