taoCMS是基于php+sqlite/mysql的国内最小(100Kb左右)的功能完善、开源免费的CMS管理系统

PHP源码分析-数组

2013-07-31

PHP中经常使用数组,使用数组最大的好处便是速度!读写都可以在O(1)内完成,因为它每个元素的大小都是一致的,只要知道下标,便可以瞬间计算出其对应的元素在内存中的位置,从而直接取出或者写入。那么内核中是如何实现的呢?

PHP大部分功能,都是通过HashTable来实现,其中就包括数组。
HashTable即具有双向链表的优点,同时具有能与数据匹敌的操作性能。
PHP中的定义的变量保存在一个符号表里,而这个符号表其实就是一个HashTable,它的每一个元素都是一个zval*类型的变量。不仅如此,保存用户定义的函数、类、资源等的容器都是以HashTable的形式在内核中实现的。
下面分别来看在PHP、内核中如何定义数组.

PHP中定义数组:

  1. <?php  
  2.     $array = array();  
  3.     $array["key"] = "values";  
  4. ?>  

在内核中使用宏来实现:

  1. zval* array;  
  2. array_init(array);  
  3. add_assoc_string(array, "key""value", 1);  
将上述代码中的宏展开:

  1. zval* array;  
  2.       ALLOC_INIT_ZVAL(array);  
  3.       Z_TYPE_P(array) = IS_ARRAY;  
  4.   
  5.       HashTable *h;  
  6.       ALLOC_HASHTABLE(h);  
  7.       Z_ARRVAL_P(array)=h;  
  8.       zend_hash_init(h, 50, NULL,ZVAL_PTR_DTOR, 0);  
  9.   
  10.       zval* barZval;  
  11.       MAKE_STD_ZVAL(barZval);  
  12.       ZVAL_STRING(barZval, "value", 0);  
  13.       zend_hash_add(h, "key", 4, &barZval, sizeof(zval*), NULL);  


内核为我们提供了方便的宏来管理数组。

  1. //add_assoc_*系列函数:  
  2. add_assoc_null(zval *aval, char *key);  
  3. add_assoc_bool(zval *aval, char *key, zend_bool bval);  
  4. add_assoc_long(zval *aval, char *key, long lval);  
  5. add_assoc_double(zval *aval, char *key, double dval);  
  6. add_assoc_string(zval *aval, char *key, char *strval, int dup);  
  7. add_assoc_stringl(zval *aval, char *key,char *strval, uint strlen, int dup);  
  8. add_assoc_zval(zval *aval, char *key, zval *value);  
  9.   
  10. //备注:其实这些函数都是宏,都是对add_assoc_*_ex函数的封装。  
  11.   
  12. //add_index_*系列函数:  
  13. ZEND_API int add_index_long     (zval *arg, ulong idx, long n);  
  14. ZEND_API int add_index_null     (zval *arg, ulong idx           );  
  15. ZEND_API int add_index_bool     (zval *arg, ulong idx, int b    );  
  16. ZEND_API int add_index_resource (zval *arg, ulong idx, int r    );  
  17. ZEND_API int add_index_double   (zval *arg, ulong idx, double d);  
  18. ZEND_API int add_index_string   (zval *arg, ulong idx, const char *str, int duplicate);  
  19. ZEND_API int add_index_stringl  (zval *arg, ulong idx, const char *str, uint length, int duplicate);  
  20. ZEND_API int add_index_zval     (zval *arg, ulong index, zval *value);  
  21.   
  22. //add_next_index_*函数:  
  23. ZEND_API int add_next_index_long        (zval *arg, long n  );  
  24. ZEND_API int add_next_index_null        (zval *arg          );  
  25. ZEND_API int add_next_index_bool        (zval *arg, int b   );  
  26. ZEND_API int add_next_index_resource    (zval *arg, int r   );  
  27. ZEND_API int add_next_index_double      (zval *arg, double d);  
  28. ZEND_API int add_next_index_string      (zval *arg, const char *str, int duplicate);  
  29. ZEND_API int add_next_index_stringl     (zval *arg, const char *str, uint length, int duplicate);  
  30. ZEND_API int add_next_index_zval        (zval *arg, zval *value);  

add_next_index_*()
  1. PHP中        内核中  
  2. $arr[] = NULL;  add_next_index_null(arr);  
  3. $arr[] = 42;    add_next_index_long(arr, 42);  
  4. $arr[] = true;  add_next_index_bool(arr, 1);  
  5. $arr[] = 3.14;  add_next_index_double(arr, 3.14);  
  6. $arr[] = 'foo'; add_next_index_string(arr, "foo");  
  7. $arr[] = $var;  add_next_index_zval(arr, zval);  

add_index_*()

  1. PHP中            内核中  
  2. $arr[0] = NULL; add_index_null(arr, 0);  
  3. $arr[1] = 42;       add_index_long(arr, 1, 42);  
  4. $arr[2] = true;     add_index_bool(arr, 2, 1);  
  5. $arr[3] = 3.14;     add_index_double(arr, 3, 3.14);  
  6. $arr[4] = 'foo';        add_index_string(arr, 4, "foo", 1);  
  7. $arr[5] = $var;     add_index_zval(arr, 5, zval);  

add_assoc_*()

  1. $arr["abc"] = NULL; add_assoc_null(arr, "abc");  
  2. $arr["def"] = 42;   add_assoc_long(arr, "def", 42);  
  3. $arr["ghi"] = true; add_assoc_bool(arr, "ghi", 1);  
  4. $arr["jkl"]  = 3.14 add_assoc_double(arr, "jkl", 3.14);  
  5. $arr["mno"]="foo"   add_assoc_string(arr, "mno""foo", 1");  
  6. $arr["pqr"] = $var; add_assoc_zval(arr, "pqr", zval);  

下面在PHP中定义一个函数,并在其中使用数组。然后来看在内核中如何实现。

  1. <?php  
  2. function array_test(){  
  3.     $mystr = "Forty Five";  
  4.     $return_value = array();  
  5.     $return_value[42] = 123;  
  6.     $return_value[] = "test";  
  7.       
  8.     $return_value[] = $mystr;  
  9.     $return_value["double"] = 3.14;  
  10.       
  11.     $mysubarray;  
  12.     $mysubarray = array();  
  13.     $mysubarray[] = "hello";  
  14.       
  15.     $return_value["subarray"] = $mysubarray;  
  16.   
  17.     return $return_value;  
  18. }  
  19. ?>  

内核中实现:

  1. PHP_FUNCTION(array_test){  
  2.     char* mystr;  
  3.     zval* mysubarray;  
  4.   
  5.     array_init(return_value);  
  6.   
  7.     add_index_long(return_value, 42, 123);  
  8.   
  9.     add_next_index_string(return_value, "test", 1);  
  10.   
  11.     add_next_index_stringl(return_value, "test_stringl", 10, 1);  
  12.   
  13.     mystr = estrdup("Forty Five");  
  14.   
  15.     add_next_index_string(return_value, mystr, 0);  
  16.   
  17.     add_assoc_double(return_value, "double", 3.14);  
  18.   
  19.     ALLOC_INIT_ZVAL(mysubarray);  
  20.     array_init(mysubarray);  
  21.     add_next_index_string(mysubarray, "hello", 1);  
  22.     add_assoc_zval(return_value, "subarray", mysubarray);  
  23. }  
你可能会疑问上面代码中的变量return_value在哪里定义的。下面将PHP_FUNCTION展开,你就明白了。
zif_array_test(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);
没错,实际上每个函数都有一个默认的返回值return_value。
在使用RETVAL_*()、RETURN_*()作为函数返回值时,仅仅是修改return_value。

类别:技术文章 | 阅读:271818 | 评论:0 | 标签:php php内核 数组

想收藏或者和大家分享这篇好文章→

“PHP源码分析-数组”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

taoCMS发布taoCMS 3.0.2(最后更新21年03月15日),请大家速速升级,欢迎大家试用和提出您宝贵的意见建议。

捐助与联系

☟请使用新浪微博联系我☟

☟在github上follow我☟

标签云