您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關(guān)PHP7的數(shù)據(jù)類型有哪些,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
PHP中變量名→zval,變量值→zend_value。其變量內(nèi)存是通過引用計數(shù)管理的,在PHP7中引用計數(shù)在value結(jié)構(gòu)中。
頭文件在PHP源碼 /zend/zend_types.h
PHP通過zval這個結(jié)構(gòu)體來表示一個變量,而不同類型的變量值則通過zval嵌入的一個人聯(lián)合體表示,即zend_value。
zend_value是一個聯(lián)合體,其代碼如下:
ast、ptr、zv這些類型只給內(nèi)核自己使用。
PHP為字符串單獨定義了一個結(jié)構(gòu):zend_string。在zend_value中通過str指向具體結(jié)構(gòu)。
存儲字符串內(nèi)容的val比較特殊。
val并沒有使用char*類型,字符串分配時是類似這樣操作的:malloc(sizeof(zend_sting)+字符串長度),就是會多分配出一些內(nèi)存來存儲字符串內(nèi)容,這塊多出來的內(nèi)存起始位置就是val。
這樣做的好處可以省去一次內(nèi)存分配(char*),且更有助于內(nèi)存管理。
val中多出來的一個字節(jié)(結(jié)構(gòu)體中為val[1]而不是val[0])用于存儲存儲字符串的最后一個字符"\0"。
比如$a="abc",則對應(yīng)的zend_string內(nèi)存結(jié)構(gòu)如左圖:
nTableMask:這個值在散列函數(shù)根據(jù)key的hash code銀蛇元素的存儲為位置時用到。nTableMask = -nTableSize 或 nTableMask = ~nTableSize+1。
nNumUsed、nNumOfElements:當(dāng)刪除數(shù)組元素時并不會立馬從數(shù)組中刪除,而是將這個元素的類型標(biāo)為IS_UNDEF,只有在數(shù)組容量超限,需要擴容時才會刪除。
若沒有擴容,則nNumUsed將一直遞增,所以其值并不是有效的元素數(shù)。nNumOfElements則是數(shù)組中有效元素的數(shù)量,所以nNumOfElements ≤ nNumUsed。
Bucket結(jié)構(gòu)用力保存元素的key及value。而h是hash code:如果key是數(shù)值(及數(shù)值索引)那么它的值就是數(shù)值索引的值;如果key是字符串,那么它的值就是根據(jù)字符串key通過Time33算法計算得到的散列值。h值用來映射元素的存儲位置。
數(shù)組實現(xiàn):
為了實現(xiàn)散列表的有序性,PHP中的散列表在散列函數(shù)與元素數(shù)組之間加了一層映射表,這個映射表也是數(shù)組,大小與存儲元素的數(shù)組相同。
中間映射表存儲元素在實際存儲的有序數(shù)組中的下標(biāo):元素按照先后順序依次插入實際存儲數(shù)組,然后將其數(shù)組下標(biāo)按照散列函數(shù)散列出來的位置存儲在新加的映射表中。
散列函數(shù):根據(jù)key映射出元素的的存儲位置,通常會以取模作為散列函數(shù):key->h % nTableSize。但PHP采用另一種方式:nIndex = key->h | nTableMask。
在PHP數(shù)組的結(jié)構(gòu)中并沒有發(fā)現(xiàn)這個中間映射表,事實上,它與arData放在一起。在數(shù)組初始化時,同時分配用于存儲Bucket的內(nèi)存和分配相同數(shù)量的uint32_t大小的空間。然后將arData偏移到存儲元素數(shù)組的位置。
中間映射表可以通過arData向前訪問到。
哈希沖突:不同的key值可能計算得到相同的哈希值,在插入散列表時會發(fā)生沖突,因為映射表只能存儲一個元素。
解決方法:把沖突的Bucket串成鏈表,即中間映射表映射出來的是一個Bucket鏈表,而不是一個Bucket,查找時需要遍歷這個鏈表,逐個比較key,從而找到目標(biāo)元素。
HashTable會記錄與它沖突的元素在arData數(shù)組中的存儲位置。
在設(shè)置映射值時,發(fā)現(xiàn)中間映射表中要設(shè)置的位置已經(jīng)被之前插入的元素占用了(值不等于初始化的-1),那么會把已經(jīng)存在的值保存到新插入的Bucket中(即c插入后u2.next=0),然后將映射表中的值更新為新Bucket的存儲位置(即映射表中的值:2)。
引用是一種指向其他類型的結(jié)構(gòu),類似C語言中指針的概念。當(dāng)修改引用類型的變量時,其修改將反應(yīng)到實際引用的變量上。
在PHP中通過&操作符生成一個引用變量,比如$b = &$a,執(zhí)行時首先為&操作的變量分配一個zend_reference結(jié)構(gòu),這個結(jié)構(gòu)就是引用類型的結(jié)構(gòu)體,它內(nèi)嵌了一個zval,此zval的value指向原來zval的value,然后將原zval的類型修改為IS_REFERENCE,原zval的value指向新創(chuàng)建的zend_reference結(jié)構(gòu)。
例子:
$a = date("Y-m");$b = &$a;
$a為字符串,通過&$a將其轉(zhuǎn)化為引用類型并賦值給了$b,轉(zhuǎn)換后的$a的類型由IS_STRING變?yōu)镮S_REFERENCE,$a的value也轉(zhuǎn)變?yōu)閦end_reference結(jié)構(gòu),這個結(jié)構(gòu)指向原來的字符串。
$a、$b間接指向了實際的value值。
使用引用時需要注意,引用只能通過&產(chǎn)生,不能通過賦值傳遞。
如上面的例子,再把$b賦值給其他變量,那么傳遞給新變量的value將是實際引用的值,而不是引用本身。
$a = date("Y-m");$b = &$a;$c = $b; //如果想讓$c也引用指向$a/$b引用的值,則:$c = &$b
關(guān)于PHP7的數(shù)據(jù)類型有哪些就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。