數據類型 - 變量

前提必看

我們這裏看的源碼都是PHP 7.0.12版本的喲,其他的版本可能變量的實現機制在細節會有一些不同,但是我們主旨都是希望通過閱讀源碼,來幫我理解下我經常使用語言,在底層實現的原理。(哈哈,畢竟在我沒打算換一下語言,PHP還是作爲我的編程主語言的)

變量

在一門高級編程語言中,變量是我們經常用來使用的數據形式。

例如我們常常在C中這樣使用變量

#include <stdio.h>
 
int main ()
{
  int a, b, c;
 
  a = 10;
  b = 20;
  
  c = a + b;
  printf("value of c : %d \n", c);
 
  return 0;
}

但是我們在PHP卻不是這樣去使用變量,來讓我們看看PHP是怎麼使用變量的~

<?php 
 $a = "Hello World"; //string 類型
 echo $a;
 $a = 1;   //int 類型
 echo $a;
 $a = true; // bool 類型
 echo $a;
 $a = [1,2];   //array 類型
 echo $a[0];   
 $a = new object();   //object 類型
 echo $a;
 .....等等數據類型

按照我們對變量的定義,變量應該要由三個部分組成:變量名+變量類型+變量值。

呀呀,PHP就是沒有像其他的高級語言一樣去先定義變量的數據類型,而是直接使用 $ 與變量名就定義了一個變量,哇,那PHP是用C作爲底層語言支持的,那是怎麼來使用$a這樣一個變量可以支持這麼多數據類型呢。我先給出一個答案,PHP在底層數據結構使用 zval  ,zval_value 兩個數據結構去實現支持這麼複雜的類型支持和類型轉換。

變量類型

 

PHP中的變量類型從宏觀的角度可以分爲以下幾大類型

  • 標量類型:字符串,整型,浮點類型,布爾類型
  • 複合類型:數組,對象
  • 特殊類型:資源,NULL

那我們直接去看看PHP在C底層是怎麼定義這些的。下面定義數據類型對應的常量

//file:zend_types.h


/* regular data types */
#define IS_UNDEF               0
#define IS_NULL                1
#define IS_FALSE               2
#define IS_TRUE                3
#define IS_LONG                4
#define IS_DOUBLE              5
#define IS_STRING              6
#define IS_ARRAY               7
#define IS_OBJECT              8
#define IS_RESOURCE            9
#define IS_REFERENCE           10

/* constant expressions */
#define IS_CONSTANT            11
#define IS_CONSTANT_AST        12

/* fake types */
#define _IS_BOOL               13
#define IS_CALLABLE            14

/* internal types */
#define IS_INDIRECT            15
#define IS_PTR                 17

內部實現

讓我們來看下一個變量怎麼實現的。便於大家理解可以把zval = 變量名 zend_value  = 變量值  。 我們先看zval的數據結構定義

//file zend_types.h


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     var_flags;
      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 */
   } u2;
};

zend_value 的數據結構定義

//file zend_types.h


typedef union _zend_value {
   zend_long         lval;             /* long value */
   double            dval;             /* double value */
   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的數據結構,大家有沒有發現少了我們經常使用的bool類型的數據,PHP對於bool類型拆分爲了True,False類型兩個,是直接使用zval中type直接存儲IS_TRUE,IS_FALSE的

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