)又比如:
<?php
$arr[2
]= 'huixinchen';
$arr[1
]= 2007
;$arr[0
]= 2008
;foreach
($arr
as$key
=>
$val
)要完全了解清楚這個問題, 我想首先應該要大家了解php陣列的內部實現結構………
php的陣列在php中, 陣列是用一種hash結構(hashtable)來實現的, php使用了一些機制, 使得可以在o(1)的時間複雜度下實現陣列的增刪, 並同時支援線性遍歷和隨機訪問.
之前的文章中也討論過,
php的hash演算法
, 基於此, 我們做進一步的延伸.
認識hashtable之前, 首先讓我們看看hashtable的結構定義, 我加了注釋方便大家理解:
typedef
struct
_hashtable
hashtable
;<?php
$arr
= array(1
,2,3
,4,5
,);$arr
= &$arr
;var_export
($arr);
//fatal error: nesting level too deep - recursive dependency?
這個字段就是為了防治迴圈引用導致的無限迴圈而設立的.
檢視上面的結構, 可以看出, 對於hashtable, 關鍵元素就是arbuckets了, 這個是實際儲存的容器, 讓我們來看看它的結構定義:
typedef
struct
bucket
bucket
;我們注意到, 最後乙個元素, 這個是flexible array技巧, 可以節省記憶體,和方便初始化的一種做法, 有興趣的朋友可以google flexible array.
h是元素的hash值,對於數字索引的元素,h為直接索引值(通過nkeylength=0來表示是數字索引).對於數字索引來說, 索引值儲存在arkey中, 索引的長度儲存在nkeylength中.
在bucket中,實際的資料是儲存在pdata指標指向的記憶體塊中,通常這個記憶體塊是系統另外分配的。但有一種情況例外,就是當bucket儲存 的資料是乙個指標時,hashtable將不會另外請求系統分配空間來儲存這個指標,而是直接將該指標儲存到pdataptr中,然後再將pdata指向本結構成員的位址。這樣可以提高效率,減少記憶體碎片。由此我們可以看到php hashtable設計的精妙之處。如果bucket中的資料不是乙個指標,pdataptr為null(本段來自altair的」zend hashtable詳解」)
結合上面的hashtable結構, 我們來說明下hashtable的總結構圖:
深入理解php原理之foreach
), 然後通過每次fe_fetch來遞增pinternalpointer,從而實現順序遍歷.
類似的, 當我們使用, each/next系列函式來遍歷的時候, 也是通過移動陣列的內部指標而實現了順序遍歷, 這裡有乙個問題, 比如:
<?php
$arr
= array(1
,2,3
,4,5
);foreach
($arr
as$v
)while
(list
($key
, $v)=
each
($arr
))?>
huixinchen
2007
2008
所以, 如果你想在數字索引的陣列中按照索引大小遍歷, 那麼你就應該使用for, 而不是foreach
for($i=
0,$l=
count
($arr);
$i<
$l;
$i++
)
深入理解PHP之陣列 遍歷順序
經常會有人問我,php的陣列,如果用foreach來訪問,遍歷的順序是固定的麼?以什麼順序遍歷呢?比如 foreach arr as key val 又比如 arr 2 huixinchen arr 1 2007 arr 0 2008 foreach arr as key val 要完全了解清楚這個...
深入理解PHP之陣列遍歷
經常會有人問我,php的陣列,如果用foreach來訪問,遍歷的順序是固定的麼?以什麼順序遍歷呢?比如 又比如 arr 2 huixinchen arr 1 2007 arr 0 2008 foreach arr as key val 要完全了解清楚這個問題,我想首先應該要大家了解php陣列的內部實...
PHP 陣列遍歷順序理解
比如 又比如 arr 2 huixinchen arr 1 2007 arr 0 2008 foreach arr as key val 要完全了解清楚這個問題,我想首先應該要大家了解php陣列的內部實現結構 在php中,陣列是用一種hash結構 hashtable 來實現的,php使用了一些機制,...