靜態變量php
它能夠是 靜態全局變量,若是不調用unset,那麼這個靜態變量會一直存在,直到程序退出時才由Zend內存管理來釋放node
它能夠是 靜態局部變量:在函數裏定義,函數執行完後,該靜態變量不會消失ide
它能夠是 靜態成員變量:在類裏定義,它能夠在全部類的對象中共享函數
例如fetch
- <?php
- function test(){
- static $a=1;
- $a++;
- }
- test(); //$a=2
- test();//$a=3
- test();//$a=4
最後 $a=4了..spa
下面咱們從內核裏面分析它scala
static不是一個函數 ,它是一個關鍵字 ,因此只能從LEX語法分析中來查找code
打開 zend/zend_language_scanner.l 查找 static對象
找到代碼內存
- <ST_IN_SCRIPTING>"static" {
- return T_STATIC;
- }
是一個宏
再打開 zend/zend_language_pareser.l
搜 T_STATIC
找到代碼
- T_STATIC static_var_list ';'
跟進 static_var_list
找到代碼
- static_var_list:
- static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
- ;
就是這裏了..它由PHP的語法分析程序 解析成上面的代碼
zend_do_fetch_static_variable 這個函數就是了
它在zend/zend_compile.c裏定義
代碼以下
- void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC)
- {
- zval *tmp; //一個臨時變量
- zend_op *opline;
- znode lval;
- znode result;
- ALLOC_ZVAL(tmp); //申請一塊內存
- if (static_assignment) {
- *tmp = static_assignment->u.constant;
- } else {
- INIT_ZVAL(*tmp);
- }
- if (!CG(active_op_array)->static_variables) {//初始化靜態變量的HASH 鍵值
- ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
- //初始化HASH值
- zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
- }
- zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
- if (varname->op_type == IS_CONST) {
- if (Z_TYPE(varname->u.constant) != IS_STRING) {
- convert_to_string(&varname->u.constant);
- }
- }
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *varname;
- SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = ZEND_FETCH_STATIC;
- result = opline->result;
- if (varname->op_type == IS_CONST) {
- zval_copy_ctor(&varname->u.constant);
- }
- fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
- if (fetch_type == ZEND_FETCH_LEXICAL) {
- znode dummy;
- zend_do_begin_variable_parse(TSRMLS_C);
- zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
- } else {
- zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
- }
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
- /* zval_dtor(&varname->u.constant); */
- }