Zend to PHP all the variables are stored in a structured way, and the preservation of the string and the storage of the array is different, the arrays are used in the form of a hash table to save (you know the hash saved address effectively reduce conflict-hash the concept of hash list you know), The structure in PHP is shown as follows:
Copy Code code as follows:
File 1:zend/zend.h
/*
* Zval
*/
typedef struct _ZVAL_STRUCT Zval;
...
typedef Union _ZVALUE_VALUE {
Long lval; /* Long Value * *
Double Dval; /* Double Value * *
struct {
Char *val;
int Len;
} str;
HashTable *ht; /* Hash Table value * *
Zend_object_value obj;
} Zvalue_value;
struct _zval_struct {
/* Variable Information * *
Zvalue_value value; /* Value * *
Zend_uint refcount__gc;
Zend_uchar type; /* Active type */
Zend_uchar is_ref__gc;
};
The hash table is structured as follows
File 2:zend/zend_hash.h
typedef struct _HASHTABLE {
UINT Ntablesize;
UINT Ntablemask;
UINT Nnumofelements;
ULONG Nnextfreeelement;
Bucket *pinternalpointer; /* Used for element traversal * *
Bucket *plisthead;
Bucket *plisttail;
Bucket **arbuckets;
dtor_func_t Pdestructor;
Zend_bool persistent;
unsigned char napplycount;
Zend_bool bapplyprotection;
#if Zend_debug
int inconsistent;
#endif
}
HashTable;
The general variable (string) in the use of strlen to get the length of the time, actually get is ZVALUE_VALUE.STR this structure len attribute, efficiency O (1) times, special note is: Strlen in PHP and no core implementation, Instead, you use the macro definition in Zend to get:
Copy Code code as follows:
File 3:zend/zend_operators.php
#define Z_strlen (Zval) (zval). Value.str.len
...
#define Z_STRLEN_P (zval_p) Z_strlen (*zval_p)
...
#define Z_STRLEN_PP (ZVAL_PP) Z_strlen (**ZVAL_PP)
For the count operation of an array, there are actually two results, and the second argument, mode "http://www.php.net/manual/en/function.count.php" in the Count's API, indicates that the mode parameter Whether you need to recalculate, and its re-statistics will traverse the array, efficiency O (n) [n: Length], by default is not Hashtable, which will be directly output in the nnumofelements, this time the efficiency is O (1) Times: The count code is as follows:
Copy Code code as follows:
File 4:ext/standard/array.c
Php_function (count)
{
Zval *array;
Long mode = Count_normal;
if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "Z|l", &array, &mode) = = failure) {
Return
}
Switch (z_type_p (array)) {
Case Is_null:
Return_long (0);
Break
Case Is_array:
Return_long (php_count_recursive (array, mode TSRMLS_CC));
Break
.....
The realization of php_count_recursive
static int php_count_recursive (Zval *array, long mode TSRMLS_DC)/* {{* * *
{
Long cnt = 0;
Zval **element;
if (z_type_p (array) = Is_array) {
Error handling
if (z_arrval_p (array)->napplycount > 1) {
Php_error_docref (NULL tsrmls_cc, e_warning, "recursion detected");
return 0;
}
Get the length directly through the zend_hash_num_elements
CNT = zend_hash_num_elements (z_arrval_p (array));
If a need for a new statistic is specified, a circular count is entered
if (mode = = count_recursive) {
Hashposition POS;
For (ZEND_HASH_INTERNAL_POINTER_RESET_EX (z_arrval_p (array), &pos);
ZEND_HASH_GET_CURRENT_DATA_EX (z_arrval_p array), (void * * *) &element, &pos) = = SUCCESS;
ZEND_HASH_MOVE_FORWARD_EX (z_arrval_p (array), &pos)
) {
Z_arrval_p (Array)->napplycount++;
CNT + + php_count_recursive (*element, count_recursive tsrmls_cc);
Z_arrval_p (Array)->napplycount--;
}
}
}
return CNT;
}
File 5:zend/zend_hash.c
The realization of zend_hash_num_elements
ZEND_API int zend_hash_num_elements (const HashTable *HT)
{
Is_consistent (HT);
Return ht->nnumofelements;
}