← 回到文章

PHP源码阅读笔记四:count函数

PHP源码阅读笔记之count函数
在一些面试或考试中经常会看到count函数的身影,于是一探其究竟
对于非数组的count处理 在其代码中可以看到
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;
        case IS_OBJECT: {    
    #ifdef HAVE_SPL
        /* it the object implements Countable we call its count() method */
            zval *retval;

            if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) {
                zend_call_method_with_0_params(&array, NULL, NULL, "count", &retval);
                if (retval) {
                    convert_to_long_ex(&retval);
                    RETVAL_LONG(Z_LVAL_P(retval));
                    zval_ptr_dtor(&retval);
                }
            return;
            }
    #endif
        /* if not we return the number of properties (not taking visibility into account) */
            if (Z_OBJ_HT_P(array)->count_elements) {
                RETVAL_LONG(1);
                if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value) TSRMLS_CC)) {
                    return;    
              }
            }
        }
    default:    //    其它情况,如考试中常见的字符串等
        RETURN_LONG(1);
        break;
    }
}
在手册中有说明: 此函数对于对象,如果安装了 SPL,可以通过实现 Countable 接口来调用 count()。该接口只有一个方法 count(),此方法返回 count() 函数的返回值。
对于数组长度的统计,如果mode使用默认值(0),则仅显示第一维数组的长度 如下所示代码
$arr = array(1, 2, 3);
$arr2 = array($arr, $arr);
echo count($arr2), '
'; echo count($arr2, 1); /* 输出结果: 2 8 */
如果只是显示第一维数组,则直接返回保存数组的HashTable的nNumOfElements属性即可 其实现的代码为:
//    php_count_recursive函数 array.c 251行
cnt = zend_hash_num_elements(Z_ARRVAL_P(array));

ZEND_API int zend_hash_num_elements(HashTable *ht)
{
    IS_CONSISTENT(ht);

    return ht->nNumOfElements;
}
如果想直接运行HashTable的一些简单操作,猛击PHP源码中HashTable的简单示例 如果想查看了解数组存储或遍历的方式,猛击鸟哥的深入理解PHP之数组(遍历顺序)
如果启动了递归,即使用count($arr, 1) 则程序会递归调用php_count_recursive函数 针对HashTable,程序会遍历包含这一维数组的双向链表,然后再递归遍历每个节点存储的pData,真到遍历完所有的节点
【感受】 HashTable很强大,如果要计算数组的长度还是调用count函数,重复发明轮子会是一种吃力不讨好的事情!
最后更新于 2010-01-17 11:22:14