掌握 PHP7 的基本變數
PHP7欄位介紹相關基本變數。
變數的基礎結構
我們都知道PHP的變數是弱型別的,宣告的時候不需要指定型別。那麼這裡面具體是怎麼實現的呢?這就得從變數的基礎結構說起了。
zval的實作
在原始碼檔案zend_type.h 中,可以看到zval 的定義:
typedef struct _zval_struct zval;struct _zval_struct { zend_value value; /* value */ union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar type, /* active type */ zend_uchar type_flags, zend_uchar const_flags, zend_uchar reserved) /* call info for EX(This) */ } v; uint32_t type_info; } u1; union { uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t access_flags; /* class constant access flags */ uint32_t property_guard; /* single property guard */ uint32_t extra; /* not further specified */ } u2; }复制代码
zval 的結構由一個保存變數類型的值或指標的union 聯合體zend_value 以及兩個union 聯合體u1 和u2 組成
- u1
u1的作用是用來保存變數類型及其訊息,其裡面的字段用處如下:
type:記錄變數型別。 即可透過 u2.v.type 來存取到
type_flags:對應變數特有類型的標記(如常數類型,需引用計數類型,不可變類型),不同類型的變數對應的 flag 不一樣。
const_flags:常數類型的標記
reserved:保留欄位
- u2
u2 主要是輔助作用,由於結構體的記憶體對齊,所以u2 的的這塊空間有或沒有u2 都是已經佔據空間了,所以就利用起來。 u2的輔助字段裡面記錄了很多類型信息,這些信息對內部功能有很大的好處,或提升緩存友好性或減少了內存尋址的操作。這裡介紹其中部分欄位。
next:用來解決雜湊衝突問題(雜湊衝突這個目前還不明白),記錄衝突的下一個元素位置。
cache_slot:運行時快取。執行函數時會優先到快取中查找,若快取中沒有,再去全域的 function 表中查找。
num_args:函數呼叫時傳入參數的個數
access_flags:物件類別的存取標識,如public protected private 這些。
- zend_value
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } zend_value;复制代码
從 zend__value 中可以看出,long、double 類型直接儲存值,而其它類型都為指針,指向各自的結構。所以,由於 zval 這樣的結構,PHP 變數在宣告的時候不用顯示的指定其類型,因為不管你賦給變數什麼類型的值,它都能幫你找到對應的儲存結構。
以值為字串的變數為例,其結構是這樣的:

#PHP5 與PHP7 的zval 結構對比
- PHP5

- PHP7

##PHP7
可以看到php7 的zval 總的只佔16 個位元組,相較於PHP5 的zval 所佔用的48 個位元組節省了很大的記憶體。
此外,在 PHP5 中,所有的變數都在堆中申請,但是對於臨時變數來說,沒有必要在堆中申請。所以在 PHP7 中對此做了最佳化,臨時變數是直接在堆疊中申請的。
常見變數類型
以下介紹幾個常見類型的變數結構,其他更多的類型,可自行查看原始碼。
整數和浮點型
對於整數和浮點型,由於其佔用空間小,在zval 中是直接儲存的整數的值是存在lval 裡,浮點型值則是儲存在dval 裡。
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ ... }复制代码
字串
PHP 7 中定義了新的字串結構體。結構如下:
struct _zend_string { zend_refcounted_h ; zend_ulong h; /* hash value */ size_t len; char val[1]; };复制代码
上面各個欄位的意思:
gc: 變數引用訊息,所有用到引用計數的變數型別都會有這個結構。
h: 雜湊值,陣列中計算索引時會用到。 (據說這個操作為PHP7 提高了5% 的性能)
len: 字符串長度,通過這個值保證二進制安全
val: 字符串內容,變長struct,分配時按len長度申請內存 陣列
array 是 PHP 中非常強大的資料結構,它的底層實作就是普通的有序HashTable,這裡簡單看下它的結構。後續再具體深入。
typedef struct _zend_array HashTable;struct _zend_array { zend_refcounted_h gc; union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar flags, zend_uchar nApplyCount, zend_uchar nIteratorsCount, zend_uchar consistency) } v; uint32_t flags; } u; uint32_t nTableMask; Bucket *arData; uint32_t nNumUsed; uint32_t nNumOfElements; uint32_t nTableSize; uint32_t nInternalPointer; zend_long nNextFreeElement; dtor_func_t pDestructor; }复制代码
struct _zend_object { zend_refcounted_h gc; uint32_t handle; zend_class_entry *ce; const zend_object_handlers *handlers; HashTable *properties; zval properties_table[1]; };复制代码
#免費推薦:PHP7
以上是掌握 PHP7 的基本變數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

解決 PHP 7.0 中插件未顯示已安裝問題的方法:檢查插件配置並啟用插件。重新啟動 PHP 以套用配置變更。檢查插件檔案權限,確保其正確。安裝遺失的依賴項,以確保插件正常運作。如果其他步驟都失敗,則重建 PHP。其他可能原因包括外掛程式版本不相容、載入錯誤版本或 PHP 配置問題。

php7.0安裝mongo擴充的方法:1、建立mongodb使用者群組和使用者;2、下載mongodb原始碼包,並將原始碼包放到“/usr/local/src/”目錄下;3、進入“src/”目錄;4、解壓縮原始碼包;5、建立mongodb檔案目錄;6、將檔案複製到「mongodb/」目錄;7、建立mongodb設定檔並修改設定即可。

在php5中,我們可以使用fsockopen()函數來偵測TCP埠。這個函數可以用來開啟一個網路連接和進行一些網路通訊。但是在php7中,fsockopen()函數可能會遇到一些問題,例如無法開啟連接埠、無法連接到伺服器等。為了解決這個問題,我們可以使用socket_create()函數和socket_connect()函數來偵測TCP埠。

PHP伺服器環境常見的解決方法包括:確保已安裝正確的PHP版本和已複製相關檔案到模組目錄。暫時或永久停用SELinux。檢查並配置PHP.ini,確保已新增必要的擴充功能和進行正確設定。啟動或重新啟動PHP-FPM服務。檢查DNS設定是否有解析問題。

php7.0安裝部署的方法:1、到PHP官網下載與本機系統對應的安裝版本;2、將下載的zip檔案解壓縮到指定目錄;3、開啟命令列窗口,在「E:\php7」目錄下運行“php -v”命令即可。

如何在系統重啟後自動設置unixsocket的權限每次系統重啟後,我們都需要執行以下命令來修改unixsocket的權限:sudo...

在Docker環境中使用PECL安裝擴展時報錯的原因及解決方法在使用Docker環境時,我們常常會遇到一些令人頭疼的問�...

本機環境:redhat6.7系統。 nginx1.12.1,php7.1.0,程式碼使用yii2框架問題:本地的web站需要用到elasticsearch服務。當php使用本機伺服器搭建的elasticsearch時,本地的負載都是正常。當我使用aws的elasticsearchservice服務時,本地伺服器出現負載經常過高的情況。查看nginx和php日誌,發現沒有異常。系統的並發連線數也不高。這時候想到我們老闆跟我講的一個strace診斷工具。偵錯過程:找一個php的子程序idstrace-
