当前位置:首页 » 编程语言 » countphp

countphp

发布时间: 2023-05-17 16:51:57

php的count(数组)和strlen(字符串)的内部实现。

翻了下PHP内核的定义,大概心中也有了答案了

count()和strlen()都是O(1)的时间复杂度

试想一下如果strlen()需要O(N)的复杂度那未免也太慢了,字符串长度起来的话服务器不是要直接挂掉吗

这两个函数都是典型的空间换时间的做法

我们可以先看看zvalue的结构:

typedefunion_zvalue_value{
longlval;/*longvalue*/
doubledval;/*doublevalue*/
struct{
char*val;
intlen;
}str;
HashTable*ht;/*hashtablevalue*/
zend_object_valueobj;
zend_ast*ast;
}zvalue_value;

这里用的是一个联合体,当变量类型是string类型的时候附加存储多了一个len的整型变量,显而易见需要取长度直接利用记录值就可以了,自然就是O(1)

对于count()常用的参数类型应该为数组,对于继承Countable的类暂不作讨论

数组实现方式为Hashtable,直接看看他的结构吧

typedefstruct_hashtable{
uintnTableSize;//hashBucket的大小,最小为8,以2x增长。
uintnTableMask;//nTableSize-1,索引取值的优化
uintnNumOfElements;//hashBucket中当前存在的元素个数,count()函数会直接返回此值
ulongnNextFreeElement;//下一个数字索引的位置
Bucket*pInternalPointer;//当前遍历的指针(foreach比for快的原因之一)
Bucket*pListHead;//存储数组头元素指针
Bucket*pListTail;//存储数组尾元素指针
Bucket**arBuckets;//存储hash数组
dtor_func_tpDestructor;//在删除元素时执行的回调函数,用于资源的释放
zend_boolpersistent;//指出了Bucket内存分配的方式。如果persisient为TRUE,则使用操作系统本身的内存分配函数为Bucket分配内存,否则使用PHP的内存分配函数。
unsignedcharnApplyCount;//标记当前hashBucket被递归访问的次数(防止多次递归)
zend_boolbApplyProtection;//标记当前hash桶允许不允许多次访问,不允许时,最多只能递归3次
#ifZEND_DEBUG
intinconsistent;
#endif
}HashTable;

count直接获取nNumOfElements大小,所以也是O(1)

补充------------------------------------------------

count() 函数的定义在这里

/*{{{protointcount(mixedvar[,intmode])
(usuallyanarray)*/
PHP_FUNCTION(count)
{
zval*array;
zend_longmode=COUNT_NORMAL;
zend_longcnt;
zval*element;

ZEND_PARSE_PARAMETERS_START(1,2)
Z_PARAM_ZVAL(array)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(mode)
ZEND_PARSE_PARAMETERS_END();

switch(Z_TYPE_P(array)){
caseIS_NULL:
php_error_docref(NULL,E_WARNING,"");
RETURN_LONG(0);
break;
caseIS_ARRAY:
if(mode!=COUNT_RECURSIVE){
//类型为数组时调用zend内核函数zend_array_count()
cnt=zend_array_count(Z_ARRVAL_P(array));
}else{
cnt=php_count_recursive(Z_ARRVAL_P(array));
}
RETURN_LONG(cnt);
break;
caseIS_OBJECT:{
zvalretval;
/*first,wecheckifthehandlerisdefined*/
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))){
return;
}
}
/*()method*/
if(instanceof_function(Z_OBJCE_P(array),zend_ce_countable)){
zend_call_method_with_0_params(array,NULL,NULL,"count",&retval);
if(Z_TYPE(retval)!=IS_UNDEF){
RETVAL_LONG(zval_get_long(&retval));
zval_ptr_dtor(&retval);
}
return;
}

/*IfThere'snohandleranditdoesn'*/
php_error_docref(NULL,E_WARNING,"");
RETURN_LONG(1);
break;
}
default:
php_error_docref(NULL,E_WARNING,"");
RETURN_LONG(1);
break;
}
}

如果没有特别指定mode参数为 COUNT_RECURSIVE 的话(即作遍历),跳转到 zend 的数组计数函数 zend_array_count()

#definezend_hash_num_elements(ht)
(ht)->nNumOfElements

...
...

staticuint32_tzend_array_recalc_elements(HashTable*ht)
{
zval*val;
uint32_tnum=ht->nNumOfElements;

ZEND_HASH_FOREACH_VAL(ht,val){
if(Z_TYPE_P(val)==IS_INDIRECT){
if(UNEXPECTED(Z_TYPE_P(Z_INDIRECT_P(val))==IS_UNDEF)){
num--;
}
}
}ZEND_HASH_FOREACH_END();
returnnum;
}

ZEND_APIuint32_tzend_array_count(HashTable*ht)
{
uint32_tnum;
if(UNEXPECTED(ht->u.v.flags&HASH_FLAG_HAS_EMPTY_IND)){
num=zend_array_recalc_elements(ht);
if(UNEXPECTED(ht->nNumOfElements==num)){
ht->u.v.flags&=~HASH_FLAG_HAS_EMPTY_IND;
}
}elseif(UNEXPECTED(ht==&EG(symbol_table))){
num=zend_array_recalc_elements(ht);
}else{
num=zend_hash_num_elements(ht);
}
returnnum;
}

IS_REFERENCE:间接 zval 指的就是其真正的值是存储在其他地方的。注意这个IS_REFERENCE类型是不同的,间接 zval 是直接指向另外一个 zval 而不是像zend_reference结构体一样嵌入 zval。

只有当数组中有HASH_FLAG_HAS_EMPTY_IND 这个 flag 时(间接zval)才会对数组进行遍历校验,其他情况下都是直接取 数组(hash table) 里面的 nNumOfElements 的值,答案显而易见了,就是O(1)

❷ PHP的sizeof和count有什么区别

没有区别,sizeof是count的别名,所以你懂得:性能和功能都是一样的。。

答题不易,互相理解,您的采纳是我前进的动力,感谢您。
希望回答对你有帮助,如果有疑问,请继续追问

❸ PHP 一条查询语句,为什么count出来的值和select的个数不一致

//不知道你select()和count()具体是什么样的
selectevents_address_1fromeventsgroupbyevents_address_1
selectcount(events_address_1)fromeventsgroupbyevents_address_1

❹ php中count(array >=0)是什么意思,其中array是数组

ARRAY是数组 这段的意思就是说 如果数组里还有元素 就一直计数 也就是COUNT++,到最后echo count(变量数组名) 会显示出这个数组中有多少个元素,COUNT一般就是计数用的

❺ PHP中如何得到数组的长度

获取一维数组:

count()和sizeof() 都可以直接统计一维数组长度。示例如下:

$arr = Array('0','1','2','3','4','5','6','7','8','9'); echo count($arr); // 输出10

$arr = array('苹果','香蕉','桔子','西瓜','梨','葡萄'); echo sizeof($arr); // 输出6

获取二维数组长度:

count()函数有两个参数:

count($arr,COUNT_NORMAL);//默认,不检测多维数组

count($arr,COUNT_RECURSIVE);//检测多维数组

例子:

$arr = array(

0=>array('name'=>'kong','age'=>'18'),

1=>array('name'=>'liang','age'=>'30')

);

count($arr) = 2;

count($arr,COUNT_RECURSIVE) = 6;

(5)countphp扩展阅读:

PHP 在数据库方面的丰富支持,也是它迅速走红的原因之一,它支持下列的数据库或是数据文件:

Adabas 、D、 DBA、dBase 、dbm 、filePro 、Informix 、InterBase、mSQL 、Microsoft SQL Server、·MySQL、Solid、Sybase、 Oracle 、PostgreSQL

今时今日,数据库系统已经成为各个动态网站上 web 应用程序的重要组成部分。由于非常敏感和机密的数据有可能保存在数据库中,所以对数据库实施保护就显得尤为重要了。

要从数据库中提取或者存入数据,就必须经过连接数据库、发送一条合法查询、获取结果、关闭连接等步骤。目前,能完成这一系列动作的最常用的查询语言是结构化查询语言 Structured Query Language (SQL)。可以看看攻击者是如何篡改 SQL 查询语句的。

❻ php如何计算数组的单元个数

//count函数有两个参数:
//0(或COUNT_NORMAL)为默认,不检测多维数组(数组中的数组);
//1(或COUNT_RECURSIVE)为检测多维数组,
$arr=array(
0=>array('title' => '新闻1', 'viewnum' => 123, 'content' => '内容1'),
1=>array('title' => '新闻2', 'viewnum' => 99, 'content' => '内容2')
);
echo '不统计多维数组:'.count($arr,0); echo '或用sizeof为'.sizeof($arr,0);
echo "<br/>";
echo '统计多维数组:'.count($arr,1);echo '或用sizeof为'.sizeof($arr,1);

热点内容
百度扩容脚本 发布:2025-07-16 10:02:29 浏览:46
sqllike字段 发布:2025-07-16 09:58:53 浏览:145
爱肤密码多少钱 发布:2025-07-16 09:52:51 浏览:616
如何访问电脑工作组 发布:2025-07-16 09:39:24 浏览:183
动态优先权算法 发布:2025-07-16 09:39:02 浏览:201
火车wifi密码是多少啊 发布:2025-07-16 09:35:46 浏览:756
sql的视图是从中导出的 发布:2025-07-16 09:31:34 浏览:784
安卓如何打开shell窗口 发布:2025-07-16 09:28:09 浏览:313
华为荣耀备忘录文件夹 发布:2025-07-16 09:23:23 浏览:972
基于特征匹配算法 发布:2025-07-16 09:18:23 浏览:46