加入收藏 | 设为首页 | 会员中心 | 我要投稿 百客网 - 百科网 (https://www.baikewang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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
  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         返回
 

(编辑:百客网 - 百科网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!