php进阶(一)php变量类型及存储

  如大家众所周知,php支持的数据类型有int、float、string、bool、array、object、resource、null八种数据类型,php是弱类型语言,在声明变量时,并不需要指定变量类型,在实际使用变量时,才会确定变量类型。在这篇文章中,一起和大家学习一下php语言的底层变量存储结构,从而深入的理解php是如何实现弱类型语言的。

  1、变量的结构  

  变量的值存储到以下所示zval结构体中。 zval结构体定义在Zend/zend.h文件,其结构如下:

复制代码
typedef struct _zval_struct zval;
...
struct _zval_struct {
    /* Variable information */
    zvalue_value value;     /* value */
    zend_uint refcount__gc;
    zend_uchar type;    /* active type */
    zend_uchar is_ref__gc;
};
复制代码

 

  PHP使用这个结构来存储变量的所有数据。和其他编译性静态语言不同, PHP在存储变量时将变量类型也保存在同一个结构体中。这样我们就能通过这些信息获取到变量的类型。

  zval结构体中有四个字段,其含义分别为:

属性名含义默认值
refcount__gc 表示引用计数 1
is_ref__gc 表示是否为引用 0
value 存储变量的值  
type 变量具体的类型

  type的值可以为: IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT和IS_RESOURCE 之一  

2、变量类型

  前面提到变量的值存储在zvalue_value联合体中,结构体定义如下:

复制代码
typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
} zvalue_value;
复制代码

  这里使用联合体而不是用结构体是出于空间利用率的考虑,因为一个变量同时只能属于一种类型。 如果使用结构体的话将会不必要的浪费空间,而PHP中的所有逻辑都围绕变量来进行的,这样的话, 内存浪费将是十分大的。这种做法成本小但收益非常大。

  • 字符串String

  字符串类型的存储结构是一个结构体,其中多了一个字串长度的字段,len这是典型的以空间换时间的做法,获取到字符串长度的时间复杂度是O(1)

  

struct {
    char *val;
    int len;
} str;
  • 数组array

  数组是PHP中最常用,也是最强大变量类型,它可以存储其他类型的数据,而且提供各种内置操作函数。数组的存储相对于其他变量要复杂一些, 数组的值存储在zvalue_value.ht字段中,它是一个HashTable类型的数据。 PHP的数组使用哈希表来存储关联数据。哈希表是一种高效的键值对存储结构。PHP的哈希表实现中使用了两个数据结构HashTable和Bucket。 PHP所有的工作都由哈希表实现,在下节HashTable中将进行哈希表基本概念的介绍以及PHP的哈希表实现。

  • 对象Object

  在面向对象语言中,用户可以自定义所需要的类结构,包括类的属性,方法等数据。对象是类的一个具体实现。对象中保存着自身的状态和所能完成的操作。php的对象是一种复合型的数据,使用一种zend_object_value的结构体来存放。其定义如下

  

typedef struct _zend_object_value {
    zend_object_handle handle;  //  unsigned int类型,EG(objects_store).object_buckets的索引
    zend_object_handlers *handlers;
} zend_object_value;

  PHP的对象只有在运行时才会被创建,前面的章节介绍了EG宏,这是一个全局结构体用于保存在运行时的数据。 其中就包括了用来保存所有被创建的对象的对象池,EG(objects_store),而object对象值内容的zend_object_handle域就是当前 对象在对象池中所在的索引,handlers字段则是将对象进行操作时的处理函数保存起来

  

posted on   1450811640  阅读(369)  评论(0编辑  收藏  举报

编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示