php7-internal 7.7 zval的操作
擴(kuò)展中經(jīng)常會(huì)用到各種類型的zval,PHP提供了很多宏用于不同類型zval的操作,盡管我們也可以自己操作zval,但這并不是一個(gè)好習(xí)慣,因?yàn)閦val有很多其它用途的標(biāo)識(shí),如果自己去管理這些值將是非常繁瑣的一件事,所以我們應(yīng)該使用PHP提供的這些宏來操作用到的zval。
7.7.1 新生成各類型zval
PHP7將變量的引用計(jì)數(shù)轉(zhuǎn)移到了具體的value上,所以zval更多的是作為統(tǒng)一的傳輸格式,很多情況下只是臨時(shí)性使用,比如函數(shù)調(diào)用時(shí)的傳參,最終需要的數(shù)據(jù)是zval攜帶的zend_value,函數(shù)從zval取得zend_value后就不再關(guān)心zval了,這種就可以直接在棧上分配zval。分配完zval后需要將其設(shè)置為我們需要的類型以及設(shè)置其zend_value,PHP中定義的ZVAL_XXX()系列宏就是用來干這個(gè)的,這些宏第一個(gè)參數(shù)z均為要設(shè)置的zval的指針,后面為要設(shè)置的zend_value。
- ZVAL_UNDEF(z): 表示zval被銷毀
- ZVAL_NULL(z): 設(shè)置為NULL
- ZVAL_FALSE(z): 設(shè)置為false
- ZVAL_TRUE(z): 設(shè)置為true
- ZVAL_BOOL(z, b): 設(shè)置為布爾型,b為IS_TRUE、IS_FALSE,與上面兩個(gè)等價(jià)
- ZVAL_LONG(z, l): 設(shè)置為整形,l類型為zend_long,如:zval z; ZVAL_LONG(&z, 88);
- ZVAL_DOUBLE(z, d): 設(shè)置為浮點(diǎn)型,d類型為double
- ZVAL_STR(z, s): 設(shè)置字符串,將z的value設(shè)置為s,s類型為zend_string*,不會(huì)增加s的refcount,支持interned strings
- ZVAL_NEW_STR(z, s): 同ZVAL_STR(z, s),s為普通字符串,不支持interned strings
- ZVAL_STR_COPY(z, s): 將s拷貝到z的value,s類型為zend_string*,同ZVAL_STR(z, s),這里會(huì)增加s的refcount
- ZVAL_ARR(z, a): 設(shè)置為數(shù)組,a類型為zend_array*
- ZVAL_NEW_ARR(z): 新分配一個(gè)數(shù)組,主動(dòng)分配一個(gè)zend_array
- ZVAL_NEW_PERSISTENT_ARR(z): 創(chuàng)建持久化數(shù)組,通過malloc分配,需要手動(dòng)釋放
- ZVAL_OBJ(z, o): 設(shè)置為對(duì)象,o類型為zend_object*
- ZVAL_RES(z, r): 設(shè)置為資源,r類型為zend_resource*
- ZVAL_NEW_RES(z, h, p, t): 新創(chuàng)建一個(gè)資源,h為資源handle,t為type,p為資源ptr指向結(jié)構(gòu)
- ZVAL_REF(z, r): 設(shè)置為引用,r類型為zend_reference*
- ZVAL_NEW_EMPTY_REF(z): 新創(chuàng)建一個(gè)空引用,沒有設(shè)置具體引用的value
- ZVAL_NEW_REF(z, r): 新創(chuàng)建一個(gè)引用,r為引用的值,類型為zval*
- ...
7.7.2 獲取zval的值及類型
zval的類型通過Z_TYPE(zval)、Z_TYPE_P(zval*)兩個(gè)宏獲取,這個(gè)值取的就是zval.u1.v.type,但是設(shè)置時(shí)不要只修改這個(gè)type,而是要設(shè)置typeinfo,因?yàn)閦val還有其它的標(biāo)識(shí)需要設(shè)置,比如是否使用引用計(jì)數(shù)、是否可被垃圾回收、是否可被復(fù)制等等。
內(nèi)核提供了Z_XXX(zval)、Z_XXX_P(zval*)系列的宏用于獲取不同類型zval的value。
- Z_LVAL(zval)、Z_LVAL_P(zval_p): 返回zend_long
- Z_DVAL(zval)、Z_DVAL_P(zval_p): 返回double
- Z_STR(zval)、Z_STR_P(zval_p): 返回zend_string*
- Z_STRVAL(zval)、Z_STRVAL_P(zval_p): 返回char*,即:zend_string->val
- Z_STRLEN(zval)、Z_STRLEN_P(zval_p): 獲取字符串長(zhǎng)度
- Z_STRHASH(zval)、Z_STRHASH_P(zval_p): 獲取字符串的哈希值
- Z_ARR(zval)、Z_ARR_P(zval_p)、Z_ARRVAL(zval)、Z_ARRVAL_P(zval_p): 返回zend_array*
- Z_OBJ(zval)、Z_OBJ_P(zval_p): 返回zend_object*
- Z_OBJ_HT(zval)、Z_OBJ_HT_P(zval_p): 返回對(duì)象的zend_object_handlers,即zend_object->handlers
- Z_OBJ_HANDLER(zval, hf)、Z_OBJ_HANDLER_P(zv_p, hf): 獲取對(duì)象各操作的handler指針,hf為write_property、read_property等,注意:這個(gè)宏取到的為只讀,不要試圖修改這個(gè)值(如:Z_OBJ_HANDLER(obj, write_property) = xxx;),因?yàn)閷?duì)象的handlers成員前加了const修飾符
- Z_OBJCE(zval)、Z_OBJCE_P(zval_p): 返回對(duì)象的zend_class_entry*
- Z_OBJPROP(zval)、Z_OBJPROP_P(zval_p): 獲取對(duì)象的成員數(shù)組
- Z_RES(zval)、Z_RES_P(zval_p): 返回zend_resource*
- Z_RES_HANDLE(zval)、Z_RES_HANDLE_P(zval_p): 返回資源handle
- Z_RES_TYPE(zval)、Z_RES_TYPE_P(zval_p): 返回資源type
- Z_RES_VAL(zval)、Z_RES_VAL_P(zval_p): 返回資源ptr
- Z_REF(zval)、Z_REF_P(zval_p): 返回zend_reference*
- Z_REFVAL(zval)、Z_REFVAL_P(zval_p): 返回引用的zval*
除了這些與PHP變量類型相關(guān)的宏之外,還有一些內(nèi)核自己使用類型的宏:
//獲取indirect的zval,指向另一個(gè)zval #define Z_INDIRECT(zval) (zval).value.zv #define Z_INDIRECT_P(zval_p) Z_INDIRECT(*(zval_p))#define Z_CE(zval) (zval).value.ce #define Z_CE_P(zval_p) Z_CE(*(zval_p))#define Z_FUNC(zval) (zval).value.func #define Z_FUNC_P(zval_p) Z_FUNC(*(zval_p))#define Z_PTR(zval) (zval).value.ptr #define Z_PTR_P(zval_p) Z_PTR(*(zval_p))7.7.3 類型轉(zhuǎn)換
//將原類型轉(zhuǎn)為特定類型,會(huì)更改原來的值 ZEND_API void ZEND_FASTCALL convert_to_long(zval *op); ZEND_API void ZEND_FASTCALL convert_to_double(zval *op); ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base); ZEND_API void ZEND_FASTCALL convert_to_null(zval *op); ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op); ZEND_API void ZEND_FASTCALL convert_to_array(zval *op); ZEND_API void ZEND_FASTCALL convert_to_object(zval *op);#define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); } #define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }//獲取格式化為long的值,不會(huì)更改原來的值,op類型為zval*,返回值為zend_long #define zval_get_long(op) _zval_get_long((op)) //獲取格式化為double的值,返回值double #define zval_get_double(op) _zval_get_double((op)) //獲取格式化為string的值,返回值z(mì)end_string * #define zval_get_string(op) _zval_get_string((op))//字符串轉(zhuǎn)整形 ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, int str_len); ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len);//判斷是否為true #define zval_is_true(op) \zend_is_true(op)7.7.4 引用計(jì)數(shù)
在擴(kuò)展中操作與PHP用戶空間相關(guān)的變量時(shí)需要考慮是否需要對(duì)其引用計(jì)數(shù)進(jìn)行加減,比如下面這個(gè)例子:
function test($arr){ return $arr; } $a = array(1,2); $b = test($a);如果把函數(shù)test()用內(nèi)部函數(shù)實(shí)現(xiàn),這個(gè)函數(shù)接受了一個(gè)PHP用戶空間傳入的數(shù)組參數(shù),然后又返回并賦值給了PHP用戶空間的另外一個(gè)變量,這個(gè)時(shí)候就需要增加傳入數(shù)組的refcount,因?yàn)檫@個(gè)數(shù)組由PHP用戶空間分配,函數(shù)調(diào)用前refcount=1,傳到內(nèi)部函數(shù)時(shí)相當(dāng)于賦值給了函數(shù)的參數(shù),因此refcount增加了1變?yōu)?,這次增加在函數(shù)執(zhí)行完釋放參數(shù)時(shí)會(huì)減掉,等返回并賦值給$b后此時(shí)共有兩個(gè)變量指向這個(gè)數(shù)組,所以內(nèi)部函數(shù)需要增加refcount,增加的引用是給返回值的。test()翻譯成內(nèi)部函數(shù):
PHP_FUNCTION(test) { zval *arr;if(zend_parse_parameters(ZEND_NUM_ARGS(), "a", &arr) == FAILURE){RETURN_FALSE;}//如果注釋掉下面這句將導(dǎo)致core dumpedZ_TRY_ADDREF_P(arr);RETURN_ARR(Z_ARR_P(arr)); }那么在哪些情況下需要考慮設(shè)置引用計(jì)數(shù)呢?一個(gè)關(guān)鍵條件是:操作的是與PHP用戶空間相關(guān)的變量,包括對(duì)用戶空間變量的修改、賦值,要明確的一點(diǎn)是引用計(jì)數(shù)是用來解決多個(gè)變量指向同一個(gè)value問題的,所以在PHP中來回傳遞zval的時(shí)候就需要考慮下是不是要修改引用計(jì)數(shù),下面總結(jié)下PHP中常見的會(huì)對(duì)引用計(jì)數(shù)進(jìn)行操作的情況:
- (1)變量賦值: 變量賦值是最常見的情況,一個(gè)用到引用計(jì)數(shù)的變量類型在初始賦值時(shí)其refcount=1,如果后面把此變量又賦值給了其他變量那么就會(huì)相應(yīng)的增加其引用計(jì)數(shù)
- (2)數(shù)組操作: 如果把一個(gè)變量插入數(shù)組中那么就需要增加這個(gè)變量的引用計(jì)數(shù),如果要?jiǎng)h除一個(gè)數(shù)組元素則要相應(yīng)的減少其引用
- (3)函數(shù)調(diào)用: 傳參實(shí)際可以當(dāng)做普通的變量賦值,將調(diào)用空間的變量賦值給被調(diào)函數(shù)空間的變量,函數(shù)返回時(shí)會(huì)銷毀函數(shù)空間的變量,這時(shí)又會(huì)減掉傳參的引用,這兩個(gè)過程由內(nèi)核完成,不需要擴(kuò)展自己處理
- (4)成員屬性: 當(dāng)把一個(gè)變量賦值給對(duì)象的成員屬性時(shí)需要增加引用計(jì)數(shù)
PHP中定義了以下宏用于引用計(jì)數(shù)的操作:
//獲取引用數(shù):pz類型為zval* #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) //設(shè)置引用數(shù) #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) //增加引用 #define Z_ADDREF_P(pz) zval_addref_p(pz) //減少引用 #define Z_DELREF_P(pz) zval_delref_p(pz)#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) #define Z_ADDREF(z) Z_ADDREF_P(&(z)) #define Z_DELREF(z) Z_DELREF_P(&(z))//只對(duì)使用了引用計(jì)數(shù)的變量類型增加引用,建議使用這個(gè) #define Z_TRY_ADDREF_P(pz) do { \if (Z_REFCOUNTED_P((pz))) { \Z_ADDREF_P((pz)); \} \ } while (0)#define Z_TRY_DELREF_P(pz) do { \if (Z_REFCOUNTED_P((pz))) { \Z_DELREF_P((pz)); \} \ } while (0)#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z)) #define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))這些宏操作類型都是zval或zval*,如果需要操作具體value的引用計(jì)數(shù)可以使用以下宏:
//直接獲取zend_value的引用,可以直接通過這個(gè)宏修改value的refcount #define GC_REFCOUNT(p) (p)->gc.refcount另外還有幾個(gè)常用的宏:
//判斷zval是否用到引用計(jì)數(shù)機(jī)制 #define Z_REFCOUNTED(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0) #define Z_REFCOUNTED_P(zval_p) Z_REFCOUNTED(*(zval_p))//根據(jù)zval獲取value的zend_refcounted頭部 #define Z_COUNTED(zval) (zval).value.counted #define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p))7.7.5 字符串操作
PHP中字符串(即:zend_string)操作相關(guān)的宏及函數(shù):
//創(chuàng)建zend_string zend_string *zend_string_init(const char *str, size_t len, int persistent);//字符串復(fù)制,只增加引用 zend_string *zend_string_copy(zend_string *s);//字符串拷貝,硬拷貝 zend_string *zend_string_dup(zend_string *s, int persistent);//將字符串按len大小重新分配,會(huì)減少s的refcount,返回新的字符串 zend_string *zend_string_realloc(zend_string *s, size_t len, int persistent);//延長(zhǎng)字符串,與zend_string_realloc()類似,不同的是len不能小于s的長(zhǎng)度 zend_string *zend_string_extend(zend_string *s, size_t len, int persistent);//截?cái)嘧址?#xff0c;與zend_string_realloc()類似,不同的是len不能大于s的長(zhǎng)度 zend_string *zend_string_truncate(zend_string *s, size_t len, int persistent);//獲取字符串refcount uint32_t zend_string_refcount(const zend_string *s);//增加字符串refcount uint32_t zend_string_addref(zend_string *s);//減少字符串refcount uint32_t zend_string_delref(zend_string *s);//釋放字符串,減少refcount,為0時(shí)銷毀 void zend_string_release(zend_string *s);//銷毀字符串,不管引用計(jì)數(shù)是否為0 void zend_string_free(zend_string *s);//比較兩個(gè)字符串是否相等,區(qū)分大小寫,memcmp() zend_bool zend_string_equals(zend_string *s1, zend_string *s2);//比較兩個(gè)字符串是否相等,不區(qū)分大小寫 #define zend_string_equals_ci(s1, s2) \(ZSTR_LEN(s1) == ZSTR_LEN(s2) && !zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)))//其它宏,zstr類型為zend_string* #define ZSTR_VAL(zstr) (zstr)->val //獲取字符串 #define ZSTR_LEN(zstr) (zstr)->len //獲取字符串長(zhǎng)度 #define ZSTR_H(zstr) (zstr)->h //獲取字符串哈希值 #define ZSTR_HASH(zstr) zend_string_hash_val(zstr) //計(jì)算字符串哈希值除了上面這些,還有很多字符串大小轉(zhuǎn)換、字符串比較的API定義在zend_operators.h中,這里不再列舉。
7.7.6 數(shù)組操作
7.7.6.1 創(chuàng)建數(shù)組
創(chuàng)建一個(gè)新的HashTable分為兩步:首先是分配zend_array內(nèi)存,這個(gè)可以通過ZVAL_NEW_ARR()宏分配,也可以自己直接分配;然后初始化數(shù)組,通過zend_hash_init()宏完成,如果不進(jìn)行初始化數(shù)組將無法使用。
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) \_zend_hash_init((ht), (nSize), (pDestructor), (persistent) ZEND_FILE_LINE_CC)- ht: 數(shù)組地址HashTable*,如果內(nèi)部使用可以直接通過emalloc分配
- nSize: 初始化大小,只是參考值,這個(gè)值會(huì)被對(duì)齊到2^n,最小為8
- pHashFunction: 無用,設(shè)置為NULL即可
- pDestructor: 刪除或更新數(shù)組元素時(shí)會(huì)調(diào)用這個(gè)函數(shù)對(duì)操作的元素進(jìn)行處理,比如將一個(gè)字符串插入數(shù)組,字符串的refcount增加,刪除時(shí)不是簡(jiǎn)單的將元素的Bucket刪除就可以了,還需要對(duì)其refcount進(jìn)行處理,這個(gè)函數(shù)就是進(jìn)行清理工作的
- persistent: 是否持久化
示例:
zval array; uint32_t size;ZVAL_NEW_ARR(&array); zend_hash_init(Z_ARRVAL(array), size, NULL, ZVAL_PTR_DTOR, 0);7.7.6.2 插入、更新元素
數(shù)組元素的插入、更新主要有三種情況:key為zend_string、key為普通字符串、key為數(shù)值索引,相關(guān)的宏及函數(shù):
// 1) key為zend_string//插入或更新元素,會(huì)增加key的refcount #define zend_hash_update(ht, key, pData) \_zend_hash_update(ht, key, pData ZEND_FILE_LINE_CC)//插入或更新元素,當(dāng)Bucket類型為indirect時(shí),將pData更新至indirect的值,而不是更新Bucket #define zend_hash_update_ind(ht, key, pData) \_zend_hash_update_ind(ht, key, pData ZEND_FILE_LINE_CC)//添加元素,與zend_hash_update()類似,不同的地方在于如果元素已經(jīng)存在則不會(huì)更新 #define zend_hash_add(ht, key, pData) \_zend_hash_add(ht, key, pData ZEND_FILE_LINE_CC)//直接插入元素,不管key存在與否,如果存在也不覆蓋原來元素,而是當(dāng)做哈希沖突處理,所有會(huì)出現(xiàn)一個(gè)數(shù)組中key相同的情況,慎用!!! #define zend_hash_add_new(ht, key, pData) \_zend_hash_add_new(ht, key, pData ZEND_FILE_LINE_CC)// 2) key為普通字符串:char*//與上面幾個(gè)對(duì)應(yīng),這里的key為普通字符串,會(huì)自動(dòng)生成zend_string的key #define zend_hash_str_update(ht, key, len, pData) \_zend_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC) #define zend_hash_str_update_ind(ht, key, len, pData) \_zend_hash_str_update_ind(ht, key, len, pData ZEND_FILE_LINE_CC) #define zend_hash_str_add(ht, key, len, pData) \_zend_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC) #define zend_hash_str_add_new(ht, key, len, pData) \_zend_hash_str_add_new(ht, key, len, pData ZEND_FILE_LINE_CC)// 3) key為數(shù)值索引//插入元素,h為數(shù)值 #define zend_hash_index_add(ht, h, pData) \_zend_hash_index_add(ht, h, pData ZEND_FILE_LINE_CC)//與zend_hash_add_new()類似 #define zend_hash_index_add_new(ht, h, pData) \_zend_hash_index_add_new(ht, h, pData ZEND_FILE_LINE_CC)//更新第h個(gè)元素 #define zend_hash_index_update(ht, h, pData) \_zend_hash_index_update(ht, h, pData ZEND_FILE_LINE_CC)//使用自動(dòng)索引值 #define zend_hash_next_index_insert(ht, pData) \_zend_hash_next_index_insert(ht, pData ZEND_FILE_LINE_CC)#define zend_hash_next_index_insert_new(ht, pData) \_zend_hash_next_index_insert_new(ht, pData ZEND_FILE_LINE_CC)7.7.6.3 查找元素
//根據(jù)zend_string key查找數(shù)組元素 ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key);//根據(jù)普通字符串key查找元素 ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *key, size_t len);//獲取數(shù)值索引元素 ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h);//判斷元素是否存在 ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key); ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len); ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h);//獲取數(shù)組元素?cái)?shù) #define zend_hash_num_elements(ht) \(ht)->nNumOfElements //與zend_hash_num_elements()類似,會(huì)有一些特殊處理 ZEND_API uint32_t zend_array_count(HashTable *ht);7.7.6.4 刪除元素
//刪除key ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key);//與zend_hash_del()類似,不同地方是如果元素類型為indirect則同時(shí)銷毀indirect的值 ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key); ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *key, size_t len); ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len); ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h); ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p);7.7.6.5 遍歷
數(shù)組遍歷類似foreach的用法,在擴(kuò)展中可以通過如下的方式遍歷:
zval *val; ZEND_HASH_FOREACH_VAL(ht, val) {... } ZEND_HASH_FOREACH_END();遍歷過程中會(huì)把數(shù)組元素賦值給val,除了上面這個(gè)宏還有很多其他用于遍歷的宏,這里列幾個(gè)比較常用的:
//遍歷獲取所有的數(shù)值索引 #define ZEND_HASH_FOREACH_NUM_KEY(ht, _h) \ZEND_HASH_FOREACH(ht, 0); \_h = _p->h;//遍歷獲取所有的key #define ZEND_HASH_FOREACH_STR_KEY(ht, _key) \ZEND_HASH_FOREACH(ht, 0); \_key = _p->key;//上面兩個(gè)的聚合 #define ZEND_HASH_FOREACH_KEY(ht, _h, _key) \ZEND_HASH_FOREACH(ht, 0); \_h = _p->h; \_key = _p->key;//遍歷獲取數(shù)值索引key及value #define ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, _h, _val) \ZEND_HASH_FOREACH(ht, 0); \_h = _p->h; \_val = _z;//遍歷獲取key及value #define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val) \ZEND_HASH_FOREACH(ht, 0); \_key = _p->key; \_val = _z;#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \ZEND_HASH_FOREACH(ht, 0); \_h = _p->h; \_key = _p->key; \_val = _z;7.7.6.6 其它操作
//合并兩個(gè)數(shù)組,將source合并到target,overwrite為元素沖突時(shí)是否覆蓋 #define zend_hash_merge(target, source, pCopyConstructor, overwrite) \_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)//導(dǎo)出數(shù)組 ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source); #define zend_hash_sort(ht, compare_func, renumber) \zend_hash_sort_ex(ht, zend_sort, compare_func, renumber)數(shù)組排序,compare_func為typedef int (*compare_func_t)(const void *, const void ),需要自己定義比較函數(shù),參數(shù)類型為Bucket,renumber表示是否更改鍵值,如果為1則會(huì)在排序后重新生成各元素的h。PHP中的sort()、rsort()、ksort()等都是基于這個(gè)函數(shù)實(shí)現(xiàn)的。
7.7.6.7 銷毀數(shù)組
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht);來源:https://github.com/pangudashu/php7-internal/blob/master/7/var.md
總結(jié)
以上是生活随笔為你收集整理的php7-internal 7.7 zval的操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 间接引语(说一说间接引语的简介)
- 下一篇: 憾生(说一说憾生的简介)