你們都知道php是一個弱類型的語言,變量的類型是隨着賦值的類型變化的,php的底層是用C寫的,C自己是一個強類型的語言,那php在底層是怎麼實現類型的呢?php
其實在底層,php是經過一個結構體來存儲全部的變量的。結構體以下:數組
typedef struct _zval_struct zval typedef struct _zval_struct { /* Variable information */ zvalue_value value; zend_uint refcount_gc; zend_uchar type; zend_uint is_ref_gc; }
解釋一下幾個變量的意義:zend_value value
儲存的值,此處是一個指針,指到一個union
的指針。php
自己的值就是存儲在這個聯合體中。zend_uint is_refcount
存儲的是引用計數zend_uchar type
存儲變量的類型。zend_uint is_ref_gc
是不是引用傳值。函數
php中全部的結構都是從用這個結構實現的。其中最關鍵的字段就是裏面的type
字段了。type
字段總共有7個值,分別是IS_NULL,IS_BOOL,IS_LONG,IS_DOUBLE,IS_STRING,ISARRAY,IS_OBJECT,IS_RESOURCE
。
這個裏面包含了全部的php基本類型:ui
標量類型: 複合類型: 特殊類型: IS_BOOL,IS_lONG,IS_DOUBLE,IS_STRINGIS_ARRAY,IS_OBJECTIS_RESOURCE,IS_NULL
zval
結構根據不一樣的類型,其zval
結構中的zval
字段指向的聯合體中存儲不一樣的值.這個聯合體就是php
中同一個變量能夠存儲不一樣的值的關鍵.結構以下:指針
typedef union _zval_value{ long *lval; double *dval; struct { char *val; int len; }str; HashTable *ht; zend_object_value obj; }
從這個結構裏能夠看出php
中全部變量的痕跡:
IS_BOOL(boolen),是存儲在lval
裏面,和整數存儲師同樣的。這裏你們應該想到==
和===
對於false
和0
處理的不一樣之處了。
IS_LONG(整型),存儲在lval
IS_DOUBLE(浮點型),存儲在dval
IS_STRING(字符串),存儲在str
IS_ARRAY(數組),存儲在*ht
哈希table中
IS_OBJECT(對象),存儲在zend_object_value
IS_NULL,NULL值在這個結構中不用存儲,直接在zval
結構中的type
字段進行判斷。code
簡單的介紹一下字符串的存儲:
字符串的在聯合體中使用結構體的形式出現,代碼以下:orm
struct { char *val; int len; }str;
能夠看到,php
在存儲字符串時,將字符串的內容和長度都存了起來,這是爲了不重複計算字符串的長度。php
中的函數strlen
,就是直接返回了這個長度。對象