<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                在PHP中,函數有自己的作用域,同時在其內部可以實現各種語句的執行,最后返回最終結果值。在PHP的源碼中可以發現,Zend引擎將函數分為以下類型: #define ZEND_INTERNAL_FUNCTION 1 #define ZEND_USER_FUNCTION 2 #define ZEND_OVERLOADED_FUNCTION 3 #define ZEND_EVAL_CODE 4 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 其中的_ZEND_USER_FUNCTION_是用戶函數,_ZEND_INTERNAL_FUNCTION_是內置的函數。也就是說PHP將內置的函數和用戶定義的函數分別保存。 ### 1.用戶函數(ZEND_USER_FUNCTION)[]() 用戶自定義函數是非常常用的函數種類,如下面的代碼,定義了一個用戶自定義的函數: <?php ? function tipi( $name ){ $return = "Hi! " . $name; [echo](http://www.php.net/echo) $return; return $return; } ? ?> 這個示例中,對自定義函數傳入了一個參數,并將其與_Hi!_ 一起輸出并做為返回值返回。從這個例子可以看出函數的基本特點:運行時聲明、可以傳參數、有值返回。當然,有些函數只是進行一些操作,并不一定顯式的有返回值,在PHP的實現中,即使沒有顯式的返回,Zend引擎也會“幫你“返回NULL。 通過 [<<第六節 變量的作用域>>](#) 可知,ZE在執行過程中,會將運行時信息存儲于_zend_execute_data中: struct _zend_execute_data { //...省略部分代碼 zend_function_state function_state; zend_function *fbc; /* Function Being Called */ //...省略部分代碼 }; 在程序初始化的過程中,function_state也會進行初始化,function_state由兩個部分組成: typedef struct _zend_function_state { zend_function *function; void **arguments; } zend_function_state; **arguments是一個指向函數參數的指針,而函數體本身則存儲于*function中, *function是一個zend_function結構體,它最終存儲了用戶自定義函數的一切信息,它的具體結構是這樣的: typedef union _zend_function { zend_uchar type; /* 如用戶自定義則為 #define ZEND_USER_FUNCTION 2 MUST be the first element of this struct! */ ? struct { zend_uchar type; /* never used */ char *function_name; //函數名稱 zend_class_entry *scope; //函數所在的類作用域 zend_uint fn_flags; // 作為方法時的訪問類型等,如ZEND_ACC_STATIC等 union _zend_function *prototype; //函數原型 zend_uint num_args; //參數數目 zend_uint required_num_args; //需要的參數數目 zend_arg_info *arg_info; //參數信息指針 zend_bool pass_rest_by_reference; unsigned char return_reference; //返回值 } common; ? zend_op_array op_array; //函數中的操作 zend_internal_function internal_function; } zend_function; _zend_function_的結構中的op_array存儲了該函數中所有的操作,當函數被調用時,ZE就會將這個op_array中的opline一條條順次執行,并將最后的返回值返回。從VLD擴展中查看的關于函數的信息可以看出,函數的定義和執行是分開的,一個函數可以作為一個獨立的運行單元而存在。 ### 2.內部函數(ZEND_INTERNAL_FUNCTION)[]() ZEND_INTERNAL_FUNCTION函數是由擴展、PHP內核、Zend引擎提供的內部函數,一般用“C/C++”編寫,可以直接在用戶腳本中調用的函數。如下為內部函數的結構: typedef struct _zend_internal_function { /* Common elements */ zend_uchar type; char * function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; /* END of common elements */ ? void (*handler)(INTERNAL_FUNCTION_PARAMETERS); struct _zend_module_entry *module; } zend_internal_function; 最常見的操作是在模塊初始化時,ZE會遍歷每個載入的擴展模塊,然后將模塊中function_entry中指明的每一個函數(module->functions),創建一個zend_internal_function結構, 并將其type設置為ZEND_INTERNAL_FUNCTION,將這個結構填入全局的函數表(HashTable結構);函數設置及注冊過程見 Zend/zend_API.c文件中的 **zend_register_functions**函數。這個函數除了處理函數,也處理類的方法,包括那些魔術方法。 內部函數的結構與用戶自定義的函數結構基本類似,有一些不同, - 調用方法,handler字段. 如果是ZEND_INTERNAL_FUNCTION, 那么ZE就調用zend_execute_internal,通過zend_internal_function.handler來執行這個函數。而用戶自定義的函數需要生成中間代碼,然后通過中間代碼映射到相對就把方法調用。 - 內置函數在結構中多了一個module字段,表示屬于哪個模塊。不同的擴展其模塊不同。 - type字段,在用戶自定義的函數中,type字段幾乎無用,而內置函數中的type字段作為幾種內部函數的區分。 ### 3.變量函數[]() PHP 支持變量函數的概念。這意味著如果一個變量名后有圓括號,PHP 將尋找與變量的值同名的函數,并且將嘗試執行它。除此之外,這個可以被用于實現回調函數,函數表等。對比使用變量函數和內部函數的調用: 變量函數$func $func = 'print_r'; $func('i am print_r function.'); 通過VLD來查看這段代碼編譯后的中間代碼: function name: (null) number of ops: 9 compiled vars: !0 = $func line # * op fetch ext return operands -------------------------------------------------------------------------------- - 2 0 > EXT_STMT 1 ASSIGN !0, 'print_r' 3 2 EXT_STMT 3 INIT_FCALL_BY_NAME !0 4 EXT_FCALL_BEGIN 5 SEND_VAL 'i+am+print_r+function.' 6 DO_FCALL_BY_NAME 1 7 EXT_FCALL_END 8 > RETURN 1 內部函數print_r [print_r](http://www.php.net/print_r)('i am print_r function.'); 通過VLD來查看這段代碼編譯后的中間代碼: function name: (null) number of ops: 6 compiled vars: none line # * op fetch ext return operands -------------------------------------------------------------------------------- - 2 0 > EXT_STMT 1 EXT_FCALL_BEGIN 2 SEND_VAL 'i+am+print_r+function.' 3 DO_FCALL 1 'print_r' 4 EXT_FCALL_END 5 > RETURN 1 對比發現,二者在調用的中間代碼上存在一些區別。變量函數是DO_FCALL_BY_NAME,而內部函數是DO_FCALL。這在語法解析時就已經決定了,見Zend/zend_complie.c文件的zend_do_end_function_call函數中部分代碼: if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) { opline->opcode = ZEND_DO_FCALL; opline->op1 = *function_name; ZVAL_LONG(&opline->op2.u.constant, zend_hash_func(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant) + 1)); } else { opline->opcode = ZEND_DO_FCALL_BY_NAME; SET_UNUSED(opline->op1); } 如果不是方法,并且不是動態調用,并且函數名為字符串常量,則其生成的中間代碼為ZEND_DO_FCALL。其它情況則為ZEND_DO_FCALL_BY_NAME。另外將變量函數作為回調函數,其處理過程在Zend/zend_complie.c文件的zend_do_pass_param函數中。最終會體現在中間代碼執行過程中的 **ZEND_SEND_VAL_SPEC_CONST_HANDLER** 等函數中。 ### 4.匿名函數[]() 匿名函數是一類不需要指定表示符,而又可以被調用的函數或子例程,匿名函數可以方便的作為參數傳遞給其他函數,關于匿名函數的詳細信息請閱讀 [<<第四節 匿名函數及閉包>>](#)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看