首頁  >  文章  >  後端開發  >  PHP變數的組成及類型

PHP變數的組成及類型

墨辰丷
墨辰丷原創
2018-06-05 16:44:271924瀏覽

本篇主要介紹PHP變數的組成及類型,有興趣的朋友參考下,希望對大家有幫助。

php變數組成部分:

變數名稱:php語言的變數名稱以$開頭英文/底線,可以包含數字、底線、字母,區分大小寫。同時PHP也支持複合變量,形如$$A,增加了php的動態性。

類型:php屬於弱型別語言,可以賦值任意型別的值。

內容:在同一時刻只能有一種值。

php語言中存在8 中資料類型,分為三大類:

#1. 標量類型:Boolean,integer,float, string;

2. 複合型別:object,array;

3. 特殊型別:NULL,resource;

php作為一種弱型別語言,實作內部所有變數是透過結構zval來儲存資料的,不僅包含變數的值,也包含變數的類型,是php弱類型的核心。

zval資料結構:

struct _zval_struct{
  zvalue_value value;    //存储变量的值
  zend_unint  refcount_gc; //引用计数
  zend_char  is_ref_gc;  // 是否为引用
  zend_char  type;     //存储变量的类型
}

其中zvalue_value並不是一個結構體,為了節省記憶體使用的union來實現的,因為在同一時刻變數只能表示一種類型。其原型:

typedef union _zvalue_value{
  long lval;         
  double dval;
  struct {
      char *val;
      int len;      //字符串的长度
    }str;
  HashTable *ht;       //保存数组
  zend_object_value obj;   //对象
}zvalue_value;

雜湊表:

php內部很多實作基於雜湊表:變數的作用域、函數表、類別的屬性、方法等, Zend引擎內部的許多資料都是保存在雜湊表中的。

php陣列使用雜湊表來儲存關聯數據,雜湊表實作使用兩個資料結構HashTable和Bucket:

HashTable:

typedef struct _hashtable { 
  uint nTableSize;    // hash Bucket的大小,最小为8,以2x增长。
  uint nTableMask;    // nTableSize-1 , 索引取值的优化
  uint nNumOfElements;  // hash Bucket中当前存在的元素个数,count()函数会直接返回此值 
  ulong nNextFreeElement; // 下一个数字索引的位置
  Bucket *pInternalPointer;  // 当前遍历的指针(foreach比for快的原因之一)
  Bucket *pListHead;     // 存储数组头元素指针
  Bucket *pListTail;     // 存储数组尾元素指针
  Bucket **arBuckets;     // 存储hash数组
  dtor_func_t pDestructor;  // 在删除元素时执行的回调函数,用于资源的释放
  zend_bool persistent;    // 指出了Bucket内存分配的方式。如果persisient为TRUE,
                  则使用操作系统本身的内存分配函数为Bucket分配内存,否则使用
                  PHP的内存分配函数。
  unsigned char nApplyCount; // 标记当前hash Bucket被递归访问的次数(防止多次递归)
  zend_bool bApplyProtection;// 标记当前hash桶允许不允许多次访问,不允许时,最多只能递归3次
#if ZEND_DEBUG
  int inconsistent;
#endif
} HashTable;

在HashTable中容量的擴增,始終調整為接近初始大小的2的整數次方。因為:

在選槽時,這裡使用&操作而不是使用取模,這是因為是相對來說取模操作的消耗和按位與的操作大很多。 mask的作用就是將雜湊值對應到插槽所能儲存的索引範圍內。例如:某個key的索引值是21, 雜湊表的大小為8,則mask為7,則求與時的二進位表示為: 10101 & 111 = 101 也就是十進位的5。因為2的整數次方-1的二進制比較特殊:後面N位的值都是1,這樣比較容易能將值進行映射, 如果是普通數字進行了二進制與之後會影響哈希值的結果。那麼由雜湊函數計算的值的平均分佈就可能出現影響。

bucket:

typedef struct bucket {
  ulong h;      // 对char *key进行hash后的值,或者是用户指定的数字索引值
  uint nKeyLength;  // hash关键字的长度,如果数组索引为数字,此值为0
  void *pData;    // 指向value,一般是用户数据的副本,如果是指针数据,则指向pDataPtr
  void *pDataPtr;   //如果是指针数据,此值会指向真正的value,同时上面pData会指向此值
  struct bucket *pListNext;  // 整个hash表的下一元素
  struct bucket *pListLast;  // 整个哈希表该元素的上一个元素
  struct bucket *pNext;    // 存放在同一个hash Bucket内的下一个元素
  struct bucket *pLast;    // 同一个哈希bucket的上一个元素
// 保存当前值所对于的key字符串,这个字段只能定义在最后,实现变长结构体
  char arKey[1];       
} Bucket;

在Bucket中儲存的是哈希值而不是哈希的索引。

上面結構體的最後一個字段用來保存key的字串,而這個字段卻申明為只有一個字符的數組, 其實這裡是一種長見的變長結構體,主要的目的是增加靈活性。以下為雜湊表插入新元素時申請空間的程式碼

p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
if (!p) {
  return FAILURE;
}
memcpy(p->arKey, arKey, nKeyLength);

#插入過程圖

雜湊演算法

php中hash函數使用DJBX33A演算法來實作。

物件:

php物件使用資料結構zend_object_value來儲存;

總結:以上就是這篇文章的全部內容,希望能對大家的學習有所幫助。

相關推薦:

PHP中的資料傳輸CURL實例分析

php新增資料到xml檔案的簡單實例分享

基於PHP實作的網站目錄掃描索引工具實例

以上是PHP變數的組成及類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn