脚本宝典收集整理的这篇文章主要介绍了54-数组源码分析,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
PHP中经常使用数组,使用数组最大的好处便是速度!读写都可以在O(1)内完成,因为它每个元素的大小都是一致的,只要知道下标,便可以瞬间计算出其对应的元素在内存中的位置,从而直接取出或者写入。那么内核中是如何实现的呢?
PHP大部分功能,都是通过HashTable来实现,其中就包括数组。HashTable即具有双向链表的优点,同时具有能与数据匹敌的操作性能。PHP中的定义的变量保存在一个符号表里,而这个符号表其实就是一个HashTable,它的每一个元素都是一个zval*类型的变量。不仅如此,保存用户定义的函数、类、资源等的容器都是以HashTable的形式在内核中实现的。
下面分别来看在PHP、内核中如何定义数组。
PHP中定义数组:
<?PHP $array = array(); $array["key"] = "values"; ?>
在内核中使用宏来实现:
zval* array; array_inIT(array); add_assoc_string(array,"key","value",1);
将上述代码中的宏展开:
zval* array; ALLOC_INIT_ZVAL(array); Z_TYPE_P(array) = IS_ARRAY; HashTable *h; ALLOC_HASHTABLE(h); Z_ARRVAL_P(array)=h; zend_hash_init(h,50,NULL,ZVAL_PTR_DTOR,0); zval* barZval; MAKE_STD_ZVAL(barZval); ZVAL_STRING(barZval,0); zend_hash_add(h,4,&barZval,sizeof(zval*),NULL);
内核为我们提供了方便的宏来管理数组。
//add_assoc_*系列函数: add_assoc_null(zval *aval,char *key); add_assoc_bool(zval *aval,char *key,zend_bool bval); add_assoc_long(zval *aval,long lval); add_assoc_double(zval *aval,double dval); add_assoc_string(zval *aval,char *strval,int dup); add_assoc_stringl(zval *aval,uint strlen,int dup); add_assoc_zval(zval *aval,zval *value); //备注:其实这些函数都是宏,都是对add_assoc_*_ex函数的封装。 //add_index_*系列函数: 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,int b ); ZEND_API int add_index_resource (zval *arg,int r ); ZEND_API int add_index_double (zval *arg,double d); ZEND_API int add_index_string (zval *arg,const char *str,int duplicate); ZEND_API int add_index_stringl (zval *arg,uint length,int duplicate); ZEND_API int add_index_zval (zval *arg,ulong index,zval *value); //add_next_index_*函数: 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,int duplicate); ZEND_API int add_next_index_stringl (zval *arg,int duplicate); ZEND_API int add_next_index_zval (zval *arg,zval *value); add_next_index_*() PHP中 内核中 $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); add_index_*() PHP中 内核中 $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,"foo",1); $arr[5] = $var; add_index_zval(arr,5,zval); add_assoc_*() $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",1"); $arr["pqr"] = $var; add_assoc_zval(arr,"pqr",zval);
下面在PHP中定义一个函数,并在其中使用数组。然后来看在内核中如何实现。
<?PHP function array_test(){ $mystr = "Forty Five"; $return_value = array(); $return_value[42] = 123; $return_value[] = "test"; $return_value[] = $mystr; $return_value["double"] = 3.14; $mysubarray; $mysubarray = array(); $mysubarray[] = "hello"; $return_value["subarray"] = $mysubarray; return $return_value; } ?>
内核中实现:
PHP_FUNCTION(array_test){ char* mystr; zval* mysubarray; array_init(return_value); add_index_long(return_value,42,123); add_next_index_string(return_value,"test",1); add_next_index_stringl(return_value,"test_stringl",10,1); mystr = estrdup("Forty Five"); add_next_index_string(return_value,mystr,0); add_assoc_double(return_value,"double",3.14); ALLOC_INIT_ZVAL(mysubarray); array_init(mysubarray); add_next_index_string(mysubarray,"hello",1); add_assoc_zval(return_value,"subarray",mysubarray); }
你可能会疑问上面代码中的变量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。
以上是脚本宝典为你收集整理的54-数组源码分析全部内容,希望文章能够帮你解决54-数组源码分析所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。