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