深入PHP核心之數組

來源:互聯網
上載者:User

標籤:

定義:

PHP 中的數組實際上是一個有序映射。映射是一種把 values 關聯到 keys 的類型。此類型在很多方面做了最佳化,因此可以把它當成真正的數組,或列表(向量),散列表(是映射的一種實現),字典,集合,棧,隊列以及更多可能性。數組元素的值也可以是另一個數組。樹形結構和多維陣列也是允許的。

這是手冊中對PHP數組的定義,本質上是一種鍵-值對應的關係,算是一種散列表(雜湊表)。

到這裡我不得不說,PHP核心中的神器了  HashTable

HashTable即具有雙向鏈表的優點,PHP中的定義的變數儲存在一個符號表裡,而這個符號表其實就是一個HashTable,它的每一個元素都是一個zval*類型的變數。不僅如此,儲存使用者定義的函數、類、資源等的容器都是以HashTable的形式在核心中實現的。

因此,PHP的數組讀寫都可以在O(1)內完成,這是非常高效的,因此開銷和C++、Java相比也就是hashtable的建立了

我們看一下PHP定義數組

<?php      $array = array();      $array["key"] = "value";  

 在核心中

zval* array;  array_init(array);  add_assoc_string(array, "key", "value", 1);

 這樣就可以了

看一下源碼是怎麼實現

在zend_API.h 檔案中,這是一個宏定義

#define array_init(arg)                 _array_init((arg), 0 ZEND_FILE_LINE_CC)

 接著看,在zend_API.c 檔案中

/* Argument parsing API -- andrei */ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */{        ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));        _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);        Z_TYPE_P(arg) = IS_ARRAY;        return SUCCESS;}/* }}} */

再接著看,在zend_alloc.h檔案中

#define ALLOC_HASHTABLE_REL(ht)         (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))

 再接著看

ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC){        uint i = 3;//初始化是為1<<3=8        SET_INCONSISTENT(HT_OK);//最大個數為1>>31 = 2^31 =2147483648        if (nSize >= 0x80000000) {                /* prevent overflow */                ht->nTableSize = 0x80000000;        } else {                while ((1U << i) < nSize) {                        i++;                }                ht->nTableSize = 1 << i;        }        ht->nTableMask = 0;     /* 0 means that ht->arBuckets is uninitialized */        ht->pDestructor = pDestructor; /* 元素的解構函式(指標) */        ht->arBuckets = (Bucket**)&uninitialized_bucket;        ht->pListHead = NULL;  /* 頭元素, 用於線性遍曆 */        ht->pListTail = NULL;  /* 尾元素, 用於線性遍曆 */        ht->nNumOfElements = 0; /* HashTable中實際元素的個數 */        ht->nNextFreeElement = 0; /* 下個空閑可用位置的數字索引 */        ht->pInternalPointer = NULL; /* 內部位置指標, 會被reset, current這些遍曆函數使用 */ht->persistent = persistent;        ht->nApplyCount = 0;/* 迴圈遍曆保護 */        ht->bApplyProtection = 1;        return SUCCESS;}

 以上是數組初始化可以參考  http://www.laruence.com/2009/08/23/1065.html

然後賦值的過程

zval* val;  MAKE_STD_ZVAL(val);  ZVAL_STRING(val, "value", 0);  zend_hash_add(h, "key", 4, &val, sizeof(zval*), NULL);  

 核心為我們提供了方便的宏來管理數組

ZEND_API int add_index_long(zval *arg, ulong idx, long n);ZEND_API int add_index_null(zval *arg, ulong idx);ZEND_API int add_index_bool(zval *arg, ulong idx, int b);ZEND_API int add_index_resource(zval *arg, ulong idx, int r);ZEND_API int add_index_double(zval *arg, ulong idx, double d);ZEND_API int add_index_string(zval *arg, ulong idx, const char *str, int duplicate);ZEND_API int add_index_stringl(zval *arg, ulong idx, const char *str, uint length, int duplicate);ZEND_API int add_index_zval(zval *arg, ulong index, zval *value);ZEND_API int add_next_index_long(zval *arg, long n);ZEND_API int add_next_index_null(zval *arg);ZEND_API int add_next_index_bool(zval *arg, int b);ZEND_API int add_next_index_resource(zval *arg, int r);ZEND_API int add_next_index_double(zval *arg, double d);ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate);ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate);ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n);ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len);ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b);ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r);ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d);ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate);ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate);ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value);#define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key)+1, __n)#define add_assoc_null(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key) + 1)#define add_assoc_bool(__arg, __key, __b) add_assoc_bool_ex(__arg, __key, strlen(__key)+1, __b)#define add_assoc_resource(__arg, __key, __r) add_assoc_resource_ex(__arg, __key, strlen(__key)+1, __r)#define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key)+1, __d)#define add_assoc_string(__arg, __key, __str, __duplicate) add_assoc_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)#define add_assoc_stringl(__arg, __key, __str, __length, __duplicate) add_assoc_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)#define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key)+1, __value)

 具體實現

$arr[] = NULL;  add_next_index_null(arr);  $arr[] = 42;    add_next_index_long(arr, 42);  $arr[] = true;  add_next_index_bool(arr, 1);  $arr[] = 3.14;  add_next_index_double(arr, 3.14);  $arr[] = ‘foo‘; add_next_index_string(arr, "foo");  $arr[] = $var;  add_next_index_zval(arr, zval);  $arr[0] = NULL; add_index_null(arr, 0);  $arr[1] = 42;       add_index_long(arr, 1, 42);  $arr[2] = true;     add_index_bool(arr, 2, 1);  $arr[3] = 3.14;     add_index_double(arr, 3, 3.14);  $arr[4] = ‘foo‘;        add_index_string(arr, 4, "foo", 1);  $arr[5] = $var;     add_index_zval(arr, 5, zval); $arr["abc"] = NULL; add_assoc_null(arr, "abc");  $arr["def"] = 42;   add_assoc_long(arr, "def", 42);  $arr["ghi"] = true; add_assoc_bool(arr, "ghi", 1);  $arr["jkl"]  = 3.14 add_assoc_double(arr, "jkl", 3.14);  $arr["mno"]="foo"   add_assoc_string(arr, "mno", "foo", 1");  $arr["pqr"] = $var; add_assoc_zval(arr, "pqr", zval);  

 擴充中測試

PHP_FUNCTION(array_test1){zval *value;zval *element;char *s="This is a test";char *key="a";MAKE_STD_ZVAL(element);MAKE_STD_ZVAL(value);array_init(value);ZVAL_STRING(element,s,strlen(s));zend_hash_update(value->value.ht,key,strlen(key)+1,(void*)&element,sizeof(zval*),NULL);ZEND_SET_SYMBOL(EG(active_symbol_table),"siren",value); }PHP_FUNCTION(array_test2){  char* str;  zval* subarray;  array_init(return_value);array_init(subarray);  add_next_index_string(return_value, "test", 1);  str = estrdup("This is a test");  add_next_index_string(return_value, str, 0);  add_assoc_double(return_value, "double", 3.14);  add_next_index_string(subarray, "hello", 1);  add_assoc_zval(return_value, "xsubarray", subarray);  }  

 

深入PHP核心之數組

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.