26 變數的儲存

2021-07-11 10:20:39 字數 2384 閱讀 1176

php中的變數型別和值是通過c語言實現的,核心具體是如何組織使用者在php中定義的變數呢?

hash table在ze核心中被廣泛使用,php變數也正是儲存在乙個hashtable實現的符號表裡。當在php中呼叫乙個函式或者類時,核心會建立乙個新的符號表,這也是為什麼在函式中無法使用函式外部定義的變數的原因。因為他們分屬兩個符號表,乙個當前作用域,乙個全域性作用域。

現在來看核心中是如何定義作用域的:

struct _zend_executor_globals ;
可以通過eg巨集來訪問變數符號表,eg(symbol_table)訪問全域性作用域的變數符號表,eg(active_symbol_table)訪問當前作用域的變數符號表。

<?php  

$foo='bar';

?>

上面這段**很簡單,建立變數foo,並賦值bar。之後的php**中就可以呼叫$foo變數了。現在看看php中定義的變數,核心中是如何實現的。偽**:

zval* foo;  

make_std_zval(foo);

zval_string(foo, "bar", 1);

zend_set_symbol( eg(active_symbol_table), "foo", foo);

通過簡單的這三步,即可實現定義php變數。簡單的原因,在於核心為我們提供了強大的巨集。現在我們將巨集分別展開。

make_std_zval應用到的巨集有:

#define     make_std_zval(zv)               alloc_zval(zv);init_pzval(zv)  

#define alloc_zval(z) zend_fast_alloc(z, zval, zval_cache_list)

#define zend_fast_alloc(p, type, fc_type) (p) = (type *) emalloc(sizeof(type))

#define init_pzval(z) (z)->refcount__gc = 1;(z)->is_ref__gc = 0;

make_std_zval(foo)展開後得到:

(foo) = (zval *) emalloc(sizeof(zval));  

(foo)->refcount__gc = 1;

(foo)->is_ref__gc = 0;

可以看出,make_std_zval做了三件事:分配記憶體、初始化zval結構中的refcount、is_ref。

zval_string應用到的巨集有:

#define zval_string(z, s, duplicate)   

#define z_strlen_p(zval_p) z_strlen(*zval_p)

#define z_strlen(zval) (zval).value.str.len

#define z_strval_p(zval_p) z_strval(*zval_p)

#define z_strval(zval) (zval).value.str.val

#define z_type_p(zval_p) z_type(*zval_p)

#define z_type(zval) (zval).type

#define is_string 6

展開後得到:

const char *__s=("foo");  

(foo).value.str.len=strlen(__s);

(foo).value.str.val=(duplicate?estrndup(__s, (zval).value.str.len):(char*)__s);

(foo).type=6;

zval_string做的工作是設定資料型別並賦值。

zend_set_symbol這裡只展開一部分巨集,因為它展開後過於複雜。

# define eg(v) (executor_globals.v)
展開部分後得到:

zend_set_symbol(executor_globals.active_symbol_table, "foo", foo);
將變數名入當前作用域符號表。之所以使用核心提供的巨集來分配記憶體、註冊變數作用域,是因為這樣能提高相容性。

變數的儲存型別

曾巨集安,華清遠見嵌入式學院 講師。我們在程式中會經常定義一些變數來儲存和處理資料。從本質上看,變數代表了一段可操作的記憶體,也可以認為變數是記憶體的符號化表示。當程式中需要使用記憶體時,可以定義某種型別的變數。此時編譯器根據變數的資料型別分配一定大小的記憶體空間。程式就可以通過變數名來訪問對應的記...

變數的儲存區

一.在c中分為這幾個儲存區 1.棧 有編譯器自動分配釋放 2.堆 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os 3.全域性區 靜態區 全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的 另一塊區域。程...

變數的儲存類別

從變數的作用域來分,變數可以分為全域性變數和區域性變數。在乙個函式內部定義的變數是區域性變數,它只是在本函式範圍內有效,在此函式外不能使用這些變數的。全域性變數可以供所有函式共用,它的有效範圍為從定義變數的位置開始到本原始檔結束。全域性變數的優點是 可以減少函式實參和形參的個數,從而減少記憶體空間以...