首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 內核探索:變數底層結構 zval、HashTable 與物件實現

     編輯:PHP 綜合知識

zval:弱類型核心

PHP 所有變數在 C 層統一用 zval 結構體:

struct _zval_struct {
    zvalue_value value;     // 聯合體:存實際值
    zend_uint refcount__gc; // 引用計數(GC 用)
    zend_uchar type;        // 類型標記 IS_LONG, IS_STRING, IS_ARRAY...
    zend_uchar is_ref__gc;  // 是否為引用 (&)
};

zvalue_value 聯合體

typedef union _zvalue_value {
    long lval;              // 整數、布爾、資源 ID
    double dval;            // 浮點數
    struct {                // 字串
        char *val;
        int len;
    } str;
    HashTable *ht;          // 陣列
    zend_object_value obj;  // 物件
} zvalue_value;

同一時刻只佔用一個欄位,實現「弱類型」動態切換。

類型常量

常量值對應欄位
IS_NULL0—
IS_LONG1lval
IS_DOUBLE2dval
IS_BOOL3lval (0/1)
IS_RESOURCE4lval (資源 ID)
IS_STRING5str
IS_ARRAY6ht
IS_OBJECT7obj

HashTable:陣列與符號表底層

typedef struct _hashtable {
    uint nTableSize;        // 槽位數,2 的冪,最小 8
    uint nTableMask;        // nTableSize - 1,用 & 代替 %
    uint nNumOfElements;    // 當前元素數,count() 直接讀取
    ulong nNextFreeElement; // 下一個數字索引
    Bucket *pInternalPointer; // foreach 指針
    Bucket *pListHead;      // 雙向鏈表頭(維持插入順序)
    Bucket *pListTail;      // 鏈表尾
    Bucket **arBuckets;     // 槽位陣列
    dtor_func_t pDestructor;// 元素刪除回調
    zend_bool persistent;   // 內存分配方式
    unsigned char nApplyCount; // 遞歸保護計數
    zend_bool bApplyProtection;
} HashTable;

Bucket 結構

typedef struct bucket {
    ulong h;                // 字串 key 的哈希值,或數字索引
    uint nKeyLength;        // key 長度,數字索引為 0
    void *pData;            // 指向值(通常是拷貝),指針陣列指向 pDataPtr
    void *pDataPtr;         // 若值為指針,此處存真實指針
    Bucket *pListNext;      // 全域鏈表下一個
    Bucket *pListLast;      // 全域鏈表上一個
    Bucket *pNext;          // 同槽位鏈表下一個
    Bucket *pLast;          // 同槽位鏈表上一個
    char arKey[1];          // 變長結構體:存字串 key
} Bucket;

哈希算法:DJBX33A

static inline ulong zend_inline_hash_func(const char *arKey, uint nKeyLength) {
    register ulong hash = 5381;
    for (uint i = 0; i < nKeyLength; i++) {
        hash = ((hash << 5) + hash) + arKey[i]; // hash * 33 + c
    }
    return hash;
}
  • 索引計算:nIndex = h & nTableMask(位運算比取模快)
  • 衝突用 pNext/pLast 鏈表解決
  • 擴容:當 nNumOfElements > nTableSize,擴容為 2 倍並重新哈希

物件:zend_object_value

typedef struct _zend_object_value {
    zend_object_handle handle; // 物件句柄(整數 ID)
    zend_object_handlers *handlers; // 方法表指針
} zend_object_value;
  • 句柄對應 EG(objects_store).object_buckets[handle] 獲取實際 zend_object
  • zend_object 包含屬性 HashTable、類項指針、引用計數
  • 多態調用:handlers->get_method() 解析方法

變數作用域與符號表

  • 全域符號表:EG(symbol_table) (HashTable)
  • 活躍符號表:EG(active_symbol_table),函數調用時切換
  • $GLOBALS 直接指向全域符號表

總結

PHP 變數底層:zval (類型+值+引用計數) + HashTable (陣列/符號表) + Bucket (鏈表+雙向列表) + DJBX33A 哈希。理解這套結構,即可洞悉 count() O(1)、foreach 依賴內部指針、引用計數 GC、陣列插入順序保持等所有行為本質。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved