countphp
❶ 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);