標頭檔案在PHP原始碼 /zend/zend_types.h
PHP通過zval這個結構體來表示一個變數,而不同型別的變數值則通過zval嵌入的一個人聯合體表示,即zend_value。
zend_value是一個聯合體,其程式碼如下:
ast、ptr、zv這些型別只給核心自己使用。
PHP為字串單獨定義了一個結構:zend_string。在zend_value中通過str指向具體結構。
儲存字串內容的val比較特殊。
val並沒有使用char*型別,字串分配時是類似這樣操作的:malloc(sizeof(zend_sting)+字串長度),就是會多分配出一些記憶體來儲存字串內容,這塊多出來的記憶體起始位置就是val。
這樣做的好處可以省去一次記憶體分配(char*),且更有助於記憶體管理。
val中多出來的一個位元組(結構體中為val[1]而不是val[0])用於儲存儲存字串的最後一個字元""。
比如$a="abc",則對應的zend_string記憶體結構如左圖:
nTableMask:這個值在雜湊函數根據key的hash code銀蛇元素的儲存為位置時用到。nTableMask = -nTableSize 或 nTableMask = ~nTableSize+1。
nNumUsed、nNumOfElements:當刪除陣列元素時並不會立馬從陣列中刪除,而是將這個元素的型別標為IS_UNDEF,只有在陣列容量超限,需要擴容時才會刪除。
若沒有擴容,則nNumUsed將一直遞增,所以其值並不是有效的元素數。nNumOfElements則是陣列中有效元素的數量,所以nNumOfElements ≤ nNumUsed。
Bucket結構用力儲存元素的key及value。而h是hash code:如果key是數值(及數值索引)那麼它的值就是數值索引的值;如果key是字串,那麼它的值就是根據字串key通過Time33演算法計算得到的雜湊值。h值用來對映元素的儲存位置。
陣列實現:
為了實現雜湊表的有序性,PHP中的雜湊表在雜湊函數與元素陣列之間加了一層對映表,這個對映表也是陣列,大小與儲存元素的陣列相同。
中間對映表儲存元素在實際儲存的有序陣列中的下標:元素按照先後順序依次插入實際儲存陣列,然後將其陣列下標按照雜湊函數雜湊出來的位置儲存在新加的對映表中。
雜湊函數:根據key對映出元素的的儲存位置,通常會以取模作為雜湊函數:key->h % nTableSize。但PHP採用另一種方式:nIndex = key->h | nTableMask。
在PHP陣列的結構中並沒有發現這個中間對映表,事實上,它與arData放在一起。在陣列初始化時,同時分配用於儲存Bucket的記憶體和分配相同數量的uint32_t大小的空間。然後將arData偏移到儲存元素陣列的位置。
中間對映表可以通過arData向前存取到。
雜湊衝突:不同的key值可能計算得到相同的雜湊值,在插入雜湊表時會發生衝突,因為對映表只能儲存一個元素。
解決方法:把衝突的Bucket串成連結串列,即中間對映表對映出來的是一個Bucket連結串列,而不是一個Bucket,查詢時需要遍歷這個連結串列,逐個比較key,從而找到目標元素。
HashTable會記錄與它衝突的元素在arData陣列中的儲存位置。
在設定對映值時,發現中間對映表中要設定的位置已經被之前插入的元素占用了(值不等於初始化的-1),那麼會把已經存在的值儲存到新插入的Bucket中(即c插入後u2.next=0),然後將對映表中的值更新為新Bucket的儲存位置(即對映表中的值:2)。
參照是一種指向其他型別的結構,類似C語言中指標的概念。當修改參照型別的變數時,其修改將反應到實際參照的變數上。
在PHP中通過&操作符生成一個參照變數,比如$b = &$a,執行時首先為&操作的變數分配一個zend_reference結構,這個結構就是參照型別的結構體,它內嵌了一個zval,此zval的value指向原來zval的value,然後將原zval的型別修改為IS_REFERENCE,原zval的value指向新建立的zend_reference結構。
例子:
$a = date("Y-m");$b = &$a;
$a為字串,通過&$a將其轉化為參照型別並賦值給了$b,轉換後的$a的型別由IS_STRING變為IS_REFERENCE,$a的value也轉變為zend_reference結構,這個結構指向原來的字串。
$a、$b間接指向了實際的value值。
使用參照時需要注意,參照只能通過&產生,不能通過賦值傳遞。
如上面的例子,再把$b賦值給其他變數,那麼傳遞給新變數的value將是實際參照的值,而不是參照本身。
$a = date("Y-m");$b = &$a;$c = $b; //如果想讓$c也參照指向$a/$b參照的值,則:$c = &$b
以上就是PHP7中的資料型別的詳細內容,更多請關注TW511.COM其它相關文章!