php如何移动数组内部指针
发布时间:2022-12-14 11:12:37 所属栏目:PHP教程 来源:
导读: php的所有变量实际上是用一个struct zval来表示的。
/* Zend/zend.h */
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long va
/* Zend/zend.h */
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long va
|
php的所有变量实际上是用一个struct zval来表示的。 /* Zend/zend.h */ 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; zend_uchar type; /* active type */ zend_uchar is_ref; }; 而数组就是其中的"HashTable *ht",实际上就是一个哈希表(Hash Table),表中的所有元素同时又组成一个双向链表php指针,它的定义为: /* 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; 这里有一个 Bucket *pInternalPointer ,就是被reset/current/next等函数用来遍历数组保存位置状态的。Bucket的实现如下,可以看到这就是个赤裸裸的链表节点。 typedef struct bucket { ulong h; /* Used for numeric indexing */ uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; char arKey[1]; /* Must be last element */ } Bucket; 而foreach的实现,则位于 ./Zend/zend_compile.h ,在解释期被flex翻译成由 zend_do_foreach_begin zend_do_foreach_cont zend_do_foreach_end 这三个函数(以及相关代码)组合起来。由于看起来比较晦涩,我就不贴出来了(实际上我也没看太懂),详情可以参考雪候鸟的这篇:深入理解PHP原理之foreach 最后附一段php代码的opcode $arr = array(1,2,3); foreach ($arr as $x) echo $x; ?> number of ops: 12 compiled vars: !0 = $arr, !1 = $x line # * op return operands ----------------------------------------------------- 2 0 > INIT_ARRAY ~0 1 用1初始化数组 1 ADD_ARRAY_ELEMENT ~0 2 添加个2 2 ADD_ARRAY_ELEMENT ~0 3 添加个3 3 ASSIGN !0, ~0 存入$arr 3 4 > FE_RESET $2 !0, ->10 $2 = FE_RESET($arr), 失败则跳到#10 5 > > FE_FETCH $3 $2, ->10 $3 = FE_FETCH($2), 失败则跳到#10 6 > ZEND_OP_DATA 7 ASSIGN !1, $3 $x = $3 4 8 ECHO !1 echo $x 9 > JMP ->5 跳到#5 10 > SWITCH_FREE $2 释放$2 5 11 > RETURN 1 返回 (编辑:百客网 - 百科网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐

