從存儲結構理解php空,null,0'0'false

相信不少開發人員對網絡上的 0 "0" null false '' 的講解司空見慣,瞭然於胸了,
但我相信總有你忽略的細節,或者從變量結構角度出發,該如何解釋。那麼看看下邊的驗證吧。
echo 'php版本:'.PHP_VERSION; //5.6.28

$a =  0; 
$b="0"; 
$c= ''; 
$d= null; 
$e = false;

echo "5個變量-原始測試類型";
	var_dump($a);//int 0
	var_dump($b);//string '0'
	var_dump($c);//string ''
	var_dump($d);//null
	var_dump($e);//boolean false

echo "<h4>empty測試</h4>";
	var_dump(empty($a));//true
	var_dump(empty($b));//true
	var_dump(empty($c));//true
	var_dump(empty($d));//true
	var_dump(empty($e));//true

echo "<hr>";
	var_dump(isset($a));//true
	var_dump(isset($b));//true
	var_dump(isset($c));//true
	var_dump(isset($d));//【false】 見結論一
	var_dump(isset($e));//true

echo "<h4>(==)雙等式測試</h4>";
	var_dump($a == $b);//true
	var_dump($a == $c);//true
	var_dump($a == $d);//true
	var_dump($a == $e);//true !!

	var_dump($b == $c);//【false】見結論二
	var_dump($b == $d);//【false】見結論二
	var_dump($b == $e);//true

	var_dump($c == $d);//true
	var_dump($c == $e);//true

echo "<h4>(===)三等式測試</h4>";
	var_dump($a === $b);//false
	var_dump($a === $c);//false
	var_dump($a === $d);//false
	var_dump($a === $e);//false

	var_dump($b === $c);//false
	var_dump($b === $d);//false
	var_dump($b === $e);//false

	var_dump($c === $d);//false
	var_dump($c === $e);//false



總結:
對於 【0 ;"0" ;'' ;null; false】五種類型
empty操作以上五個變量,都返回false
強等於(===)比較 都爲false,同強語言結果
但對於(==)比較,需要注意string類型,涉及到底層結構與類型轉換

結論一:關於變量類型的理解
1.null爲不存在之意:php底層的zval空間裏(結構見下方)沒有存其value值,只存儲了一個type標誌其 IS_NULL(所以解釋了 empty(null)=true,isset(null)=false ,isset('')=true)
2.【0 ; "0" ; "" ; false 】:這四個爲存在,php底層是開闢zval空間存儲,有value,有type

結論二:從底層結構理解
理解了上邊結論一,那麼下邊的結論就容易理解了,還不太清楚的可以詳細看下【 PHP內核的存儲機制(分離/改變)
其中的【1.zval結構】,【2.zend_uchar type】部分

string '0'與 string'' 不相等,(想一下就明白,同類型比較【1個長度】的字符串怎麼可能 等於 【0個長度】 的字符串,zal的value結構裏,對string值有len原始記錄的)
int 0 卻和 string'' 空相等,(非同類形比較,php會做類型轉換)

string '0' 與 null 不相等
int 0 與 null 相等

說白了,對於php,碰到string "0" 的等式判斷的時候,停頓注意一下就行。其他的等式判斷正常,符合大衆熟知的php開發思維。


php變量zval結構:
//存放變量的基本信息
struct _zval_struct {  
   /* Variable information */  
   zvalue_value value;  /* 變量值保存在這裏 12字節*/  
   zend_uint refcount;//4字節,變量引用計數器  
   zend_uchar type;   /* active type變量類型 1字節*/  
   zend_uchar is_ref;//是否變量被&引用,0表示非引用,1表示引用,1字節  
};  

//存放變量的值
typedef union _zvalue_value {  
   long lval;      /* long value */  
   double dval;    /* double value */  
   struct {  
   	char *val; //4字節  
   	int len;   //4字節  
   } str;  
   HashTable *ht;    /* hash table value */  
   zend_object_value obj;  
} zvalue_value;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章