PHP 作為弱型別語言,變數底層由 C 語言實現。本文剖析 zval 結構體、zvalue_value 聯合體、引用計數(refcount__gc)、型別標識(type)、引用標記(is_ref__gc)等核心機制。
| 類別 | 型別 |
|---|---|
| 標量類型 | boolean、integer、float(double)、string |
| 複合類型 | array、object |
| 特殊類型 | resource、null |
typedef struct _zval_struct zval;
struct _zval_struct {
zvalue_value value; // 變數值(聯合體)
zend_uint refcount__gc; // 引用計數,預設 1
zend_uchar type; // 型別標識:IS_NULL/IS_BOOL/IS_LONG/IS_DOUBLE/IS_STRING/IS_ARRAY/IS_OBJECT/IS_RESOURCE
zend_uchar is_ref__gc; // 是否為引用(& 符號建立)
};
typedef union _zvalue_value {
long lval; // 整數
double dval; // 浮點數
struct {
char *val; // 字串指標
int len; // 字串長度
} str;
HashTable *ht; // 陣列/物件屬性表
zend_object_value obj; // 物件
} zvalue_value;
為何用 union 而非 struct? 節省記憶體——同一時間變數僅持有一種型別的值,聯合體確保佔用空間等於**最大成員大小**,而非所有成員總和。
refcount__gc 記錄變數被多少符號表/容器引用$a = $b)增加計數;unset() 減少修改共享變數時,Zend Engine 自動複製 zval 分離存儲,保證語義正確且避免不必要複製。
| 宏定義 | PHP 型別 |
|---|---|
| IS_NULL | null |
| IS_BOOL | boolean |
| IS_LONG | integer |
| IS_DOUBLE | float |
| IS_STRING | string |
| IS_ARRAY | array |
| IS_OBJECT | object |
| IS_RESOURCE | resource |
TIPI 開源專案:PHP 變數結構深度解析
理解 zval 結構,是進階 PHP 擴展開發、效能調優、記憶體洩漏排查的基石。