PHP 반환값 반환문 사용법 자세한 설명

伊谢尔伦
풀어 주다: 2023-03-11 14:58:01
원래의
4492명이 탐색했습니다.

프로그래밍 언어에서 함수나 메소드에는 일반적으로 반환값이 있지만, 이때 이러한 함수는 일부 트랜잭션만 처리하고 반환하지 않거나 반환값이 없는 경우도 있습니다. 명확한 반환 값. Pascal 언어에는 독점 키워드 프로시저가 있습니다. PHP에서 함수에는 반환 값이 있는데, 이는 두 가지 상황, 즉 return 문을 사용하여 명시적으로 반환하는 것과 return 문 없이 NULL을 반환하는 상황으로 나눌 수 있습니다.

return 문

return 문을 사용하면 PHP는 지정된 유형의 변수를 사용자 정의 함수에 반환합니다. 소스 코드를 보는 것과 마찬가지로 return 키워드에 대한 어휘 분석과 구문 분석을 수행한 후 중간 코드를 생성합니다. 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) {         //  返回引用时不允许常量和临时变量
       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);   //  返回前执行收尾工作}
로그인 후 복사

함수의 반환 값은 프로그램이 실행될 때 *EG(return_value_ptr_ptr)에 저장됩니다. ZE 커널은 값 반환과 참조 반환을 구분하며, 이를 기준으로 상수, 임시 변수 및 기타 유형의 변수가 반환될 때 다르게 처리됩니다. 반환이 실행되기 전에 ZE 커널은 zend_leave_helper_SPEC 함수를 호출하여 함수 내부에서 사용된 변수를 지웁니다. 이것이 ZE 커널이 함수에 NULL 반환을 자동으로 추가하는 이유 중 하나입니다.

반환문이 없는 함수

PHP에는 프로시저 개념이 없고 반환값이 없는 함수만 있습니다. 그러나 반환 값이 없는 함수의 경우 PHP 커널은 반환 값으로 NULL을 추가하여 "도움을 줍니다". 이 "지원" 작업은 중간 코드를 생성할 때도 수행됩니다. 각 함수를 구문 분석할 때 zend_do_end_function_declaration 함수를 실행해야 합니다. 이 함수에는 다음과 같은 명령문이 있습니다.

zend_do_return(NULL, 0 TSRMLS_CC);
로그인 후 복사

이전 내용과 결합하면 이 명령문의 함수는 NULL을 반환하는 것임을 알 수 있습니다. 이것이 return 문이 없는 함수가 NULL을 반환하는 이유입니다.

내부 함수의 반환 값은 return_value라는 변수를 통해 전달됩니다. 이 변수는 함수의 매개변수이기도 하며, PHP_FUNCTION 함수를 확장한 후에 볼 수 있습니다. 이 매개변수에는 항상 미리 할당된 공간이 있는 zval 컨테이너가 포함되어 있으므로 return_value에 대해 먼저 MAKE_STD_ZVAL 매크로를 실행하지 않고도 해당 멤버에 직접 액세스하고 수정할 수 있습니다. 함수 결과를 더 쉽게 반환하고 zval 컨테이너의 내부 구조에 직접 액세스하는 수고를 덜기 위해 ZEND는 이러한 관련 작업을 완료하는 대규모 매크로 명령 세트를 제공합니다. 이러한 매크로는 유형과 값을 자동으로 설정합니다.

함수에서 직접 값을 반환하는 매크로:

RETURN_RESOURCE(resource)는 리소스를 반환합니다.

RETURN_BOOL(bool) 부울 값을 반환합니다.

RETURN_NULL()은 null 값을 반환합니다.

RETURN_LONG(long) 긴 정수를 반환합니다.

RETURN_DOUBLE(double)은 배정밀도 부동 소수점 숫자를 반환합니다.

RETURN_STRING(문자열, 중복)은 문자열을 반환합니다. 중복은 이 문자가 estrdup()을 사용하여 복사되는지 여부를 나타냅니다.

RETURN_STRINGL(string, length, Duplicate)은 고정 길이 문자열을 반환합니다. 나머지는 RETURN_STRING과 동일합니다. 이 매크로는 더 빠르고 바이너리 안전합니다.

RETURN_EMPTY_STRING()은 빈 문자열을 반환합니다.

RETURN_FALSE 부울 false를 반환합니다.

RETURN_TRUE 부울 true를 반환합니다.

함수 반환 값 설정을 위한 매크로:

RETVAL_RESOURCE(resource)는 반환 값을 지정된 리소스로 설정합니다.

RETVAL_BOOL(bool) 반환 값을 지정된 부울 값으로 설정합니다.

RETVAL_NULL 반환 값을 null 값으로 설정합니다.

RETVAL_LONG(long) 반환 값을 지정된 긴 정수로 설정합니다.

RETVAL_DOUBLE(double)은 반환 값을 지정된 배정밀도 부동 소수점 숫자로 설정합니다.

RETVAL_STRING(문자열, 중복)은 반환 값을 지정된 문자열로 설정합니다. 중복의 의미는 RETURN_STRING과 동일합니다.

RETVAL_STRINGL(string, length, Duplicate)은 반환 값을 지정된 고정 길이 문자열로 설정합니다. 나머지는 RETVAL_STRING과 동일합니다. 이 매크로는 더 빠르고 바이너리 안전합니다.

RETVAL_EMPTY_STRING 반환 값을 빈 문자열로 설정합니다.

RETVAL_FALSE 반환 값을 부울 false로 설정합니다.

RETVAL_TRUE는 반환 값을 부울 true로 설정합니다.

배열, 객체 등 복잡한 유형의 데이터를 반환해야 하는 경우 먼저 array_init() 및 object_init()를 호출해야 하거나 해당 해시 함수를 사용하여 return_value를 직접 연산할 수 있습니다. 이러한 유형은 주로 잡다한 것들로 구성되어 있으므로 이에 해당하는 매크로가 없습니다.



위 내용은 PHP 반환값 반환문 사용법 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿