php如何移动数组内部指针
发布时间:2022-12-13 14:32:23 所属栏目:PHP教程 来源:互联网
导读: php的所有变量实际上是用一个struct zval来表示的。
/* Zend/zend.h */
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long valu
/* Zend/zend.h */
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long valu
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 <?php
$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 返回
(编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐