• 对数组的操作其实就是对哈希表的操作

    Zend提供一组函数对HashTable操作简单封装
    服务器君一共花费 20.096 ms 进行了 4 次数据库查询,努力地为您提供了这个页面。
    广告很萌的
    • 前面讲到,PHP数组本质上就是个HashTable,因此访问数组就是对HashTable进行操作,Zend为我们提供的一组数组函数也只是对HashTable操作进行了简单封装而已。

    先来看创建数组,由于数组也是存在于zval里的,因此要先用MAKE_STD_ZVAL()宏创建一个zval,之后调用如下宏将其转化为一个空数组:

    array_init(zval*)
    

    接下来是朝数组中添加元素,这对关联数组元素和非关联数组元素要采用不同操作。

    关联数组元素

    关联数组采用char*作为key,zval*作为value,可以使用如下宏将已有的zval加入数组或者更新已有元素:

    int add_assoc_zval(zval *arr, char *key, zval *value)
    

    需要特别注意的是,Zend不会复制zval,只会简单的储存其指针,并且不关心任何引用计数,因此不能将其他变量的zval或者是栈上的zval传给它,只能用MAKE_STD_ZVAL()宏构建。

    Zend为常用的类型定义了相应的API,以简化我们的操作:

    add_assoc_long(zval *array, char *key, long n);
    add_assoc_bool(zval *array, char *key, int b);
    add_assoc_resource(zval *array, char *key, int r);
    add_assoc_double(zval *array, char *key, double d);
    add_assoc_string(zval *array, char *key, char *str, int duplicate);
    add_assoc_stringl(zval *array, char *key, char *str, uint length, int duplicate);
    add_assoc_null(zval *array, char *key);
    

    当函数发现目标元素已经存在时,会首先递减其原zval的refcount,然后才插入新zval,这就保证了原zval引用信息的正确性。这种行为是通过HashTable.pDestructor实现的,每次删除一个元素时,HashTable都将对被删元素调用这个函数指针,而数组为其HashTable设置的函数指针就是用来处理被删除zval的引用信息。

    另外,查看这些函数的源代码可以发现一个有意思的现象,它们没有直接使用HashTable操作,而是使用变量符号表操作,可见关联数组和变量符号表就是一种东西。

    Zend没有提供删除和获取数组元素的函数,此类操作只能使用HashTable函数或者是变量符号表操作。

    非关联数组元素

    非关联数组没有key,使用index作为hash,相应函数和上面关联数组的十分类似:

    add_index_zval(zval *array, uint idx, zval *value);
    add_index_long(zval *array, uint idx, long n);
    add_index_bool(zval *array, uint idx, int b);
    add_index_resource(zval *array, uint idx, int r);
    add_index_double(zval *array, uint idx, double d);
    add_index_string(zval *array, uint idx, char *str, int duplicate);
    add_index_stringl(zval *array, uint idx, char *str, uint length, int duplicate);
    add_index_null(zval *array, uint idx);
    

    如果只是想插入值,而不指定index的话,可以使用如下函数:

    add_next_index_zval(zval *array, zval *value);
    add_next_index_long(zval *array, long n);
    add_next_index_bool(zval *array, int b);
    add_next_index_resource(zval *array, int r);
    add_next_index_double(zval *array, double d);
    add_next_index_string(zval *array, char *str, int duplicate);
    add_next_index_stringl(zval *array, char *str, uint length, int duplicate);
    add_next_index_null(zval *array);
    
    • 谈到这里应该比较明晰了:PHP的数组,其实不是常规意义上的数组,而是哈希表“伪装”成的。Zend为我们提供的一组函数对这类伪数组(HashTable)的操作进行了简单封装。我们前面讨论了哈希表,那么后面用哈希表去理解PHP数组就能够深刻得多了。
更多 推荐条目

Welcome to NowaMagic Academy!

现代魔法 推荐于 2013-02-27 10:23   

本章最新发布
随机专题
  1. [Python程序设计] Tornado表单处理 3 个条目
  2. [移动开发] Android根基概念Context 8 个条目
  3. [软件工程与项目管理] 呈现树的构建 13 个条目
  4. [软件工程与项目管理] 浏览器与CSS渲染技巧 2 个条目
  5. [移动开发] 从代码角度去认识HttpClient 2 个条目
  6. [数据结构] 散列表(哈希表) 13 个条目
  7. [智力开发与知识管理] 超越整体性学习 5 个条目
  8. [数据库技术] 无限级分类数据表设计 4 个条目
  9. [智力开发与知识管理] 学习编程为什么没会这么难? 7 个条目
  10. [Python程序设计] 写几个简单的Tornado程序吧 5 个条目
  11. [数据库技术] SQL基础语法 1 个条目
  12. [移动开发] ListView 使用相关问题集 1 个条目
窗口 -- [资讯]