php 支持8种基本的数据类型:
四种标量类型:
boolean (布尔型)
integer (整型)
float (浮点型, 也称作 double)
string (字符串)
两种复合类型:
array (数组)
object (对象)
最后是两种特殊类型:
resource (资源)
NULL (NULL)
无论何种类型都存储在以下结构体+union中:
struct _zval_struct { zvalue_value value; /* 变量的值 */ zend_uint refcount__gc; zend_uchar type; /* 变量当前的数据类型 */ zend_uchar is_ref__gc; };
typedef union _zvalue_value { long lval; /* long value */ //使用long存储int的 double dval; /* double value */ //使用double存储float struct { char *val; int len; } str; //使用struct 存储string类型 HashTable *ht; /* hash table value */ //存储数组等 zend_object_value obj; //对象 } zvalue_value;
直接根据zvalue_value.type就能得到当前php变量的数据类型。
不过一般用下列宏来获取type类型:
#define Z_TYPE(zval) (zval).type #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)
更详细的关于zval介绍请移步以下链接:
https://github.com/walu/phpbook/blob/master/2.1.md
hash表:
哈希表在php内部结构几乎无处不在,最常见也是最基本的就是数组类型了
下面是2个关键struct 哈希表+槽位:
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;
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;
哈希+双向链表实现php内核中的哈希算法,bucket存储真正的数据 并会存储prev+next bucket的指针和数组中hash的前后指针。详细内容可移步以下链接:
http://www.php-internals.com/book/?p=chapt03/03-01-02-hashtable-in-php