原文链接:http://www.orlion.ga/238/

编程语言的类型可以分为强类型和弱类型两种,PHP是弱类型语言,但是C语言是强类型语言。在官网PHP实现内部,所有变量使用同一种数据结构(zval)来保存,这个结构表示PHP中的各种数据类型,它不仅包含变量的值,也包含变量的类型。这就是PHP弱类型的核心。

那zval结构是如何实现弱类型的呢?

一、PHP变量类型及存储结构

 

PHP在声明和使用变量的时候,并不需要指明其数据类型,PHP是弱类型语言,但是PHP有类型,PHP有八中数据类型,可以分成三类:标量类型:boolean、integer、float(double) string;复合类型:array、object;特殊类型:resource、NULL

C语言是如何实现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;
};

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

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

在PHP5.3之后,引入了新的垃圾回收机制,引用计数和引用的字段名改为refcout_gc和is_ref_gc在此之前为refcount和is_ref.

变量的值存储在另外一个结构体zvalue_value,值存储见下面的介绍。

2、变量类型

zval结构体的type字段就是实现弱类型最关键的字段了,type的值可以为:IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_OBJECT和IS_RESOURCE之一。除此之外和它们定义在一起的类型还有IS_CONSTANT、IS_CONSTANT_ARRAY。

二、变量的值存储

 

前面提到变量的值存储在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;

    各种类型的数据会使用不同的方法来进行变量值的存储,其对应赋值方式如下:

一般类型:

变量类型  
boolean ZVAL_BOOL

布尔型/整型的变量值存储于(zval).value.lval中,其类型也会

以相应的IS_*进行存储

integer ZVAL_LONG
float ZVAL_DOUBLE Z_TYPE_P(z)=IS_BOOL/LONG;Z_LVAL_P(z)=(b)!=0;
null ZVAL_NULL

NULL值的变量值不需要存储,只需要把(zval).type标为IS_NUL

Z_TYPE_P(z)=IS_NULL;

resource ZVAL_RESOURCE

资源类型的存储与其他一般变量无异,但其初始化及存储实现则不

同Z_TYPE_P(z) = IS_RESOURCE; Z_LVAL_P(z) = 1;

字符串

字符串的类型标示和其他数据类型一样,不过在存储字符串时多了一个字符串长度的字段。

struct {
    char *val;
    int len;
} str;

(存储字符串长度是因为字符串的操作十分频繁,有利于节省时间,是空间换时间的做法)

数组Array

    数组是PHP中最常用也是最强大变量类型。数组的值存储在zvalue_value.ht字段中,它是一个HashTable类型的数据。PHP数组使用哈希表来存储关联数据。PHP的哈希表实现中使用了两个数据结构HashTable和Bucket。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字段则是将对象进行操作时的处理函数保存起来。

PHP的弱变量容器的实现方式是兼容并包的形式体现。

深入理解PHP内核(五)变量及数据类型-变量的结构和类型的更多相关文章

  1. ECMAScript1.1 js书写位置 | 声明变量 | 基本数据类型 | 数据类型转换 | 操作符 | 布尔类型的隐式转换

    js书写位置 由于在写css样式时使用的时双引号,所以我们在写js代码时建议使用单引号(‘’)! 行内式 <input type="button" value="点 ...

  2. 深入理解PHP内核(五)函数的内部结构

    php的函数包括用户定义的函数.内部函数(print_r count...).匿名函数.变量函数($func = 'print_r'; $func(array('a','b'));) PHP内核源码中 ...

  3. Python变量及数据类型

    所有编程语言几乎都会有 ’ 变量‘ ,如 a = 2,用一个a变量指代数字2,在Python中,一切皆对象,因此在变量赋值的时候实际上是在内存中开辟了一块存储变量内容的内存空间对象. 对象可以指定不同 ...

  4. Java学习笔记之——变量与数据类型、运算符

    一.变量 1.变量:变化的值 变量在代码运行期间,开辟了一块空间 .这块空间是有地址的,给这块取了个名字, 这个名字就叫做变量名,这块空间放的东西叫做变量值 2.变量的初始化: (1)先声明再赋值: ...

  5. java 变量及数据类型、原码、反码、补码

    Java基础——变量及数据类型 变量的概念 内存中的一个存储区域 变量名+数据类型 可在同一类型范围内不断变化 为什么定义变量: 用于不断的存放同一类型的常量,并可以重复使用 使用变量注意: 变量的作 ...

  6. Java 数据类型 & 变量与常量 & 注释

    一.数据类型 1.数据类型分类 Java 的数据类型分为两大类: 基本数据类型:整数.浮点数.字符型.布尔型 引用数据类型(对象类型):类.数组,字符串.接口等. 2.基本数据类型 四类八种基本数据类 ...

  7. JAVA数据类型,变量,转换,常量,运算符

    java数据类型: Java基本类型共有八种,基本类型可以分为三类: 1.字符类型char,用单引号赋值 2.布尔类型boolean 3.数值类型byte.short.int.long.float.d ...

  8. C#变量与数据类型

    数据类型: 整型:int short long byte 小数:double float decimal 布尔:bool 字符:char 定义变量: 数据类型 变量名 [= 值]; 变量名的命名规则: ...

  9. Java基础复习之一篇:关健字,标识符,注释,常量,进制转换,变量,数据类型,数据类型转换

    1.关健字 1.1.被Java语言赋予特定意义的单词(如:class,interface,public ,static) 1.2.全部是小写 1.3.注意事项(goto和const作为关健字保留起来) ...

随机推荐

  1. 8.4.2 Fresco

    Fresco是Facebook公司的黑科技:http://fresco-cn.org/ 真三级缓存,变换后的BItmap(内存),变换前的原始图片(内存),硬盘缓存.在内存管理上做到了极致.对于重度图 ...

  2. vb- ----之常用函数

    [VB]常用函数 2007-10-25 10:52 3375人阅读 评论(1) 收藏 举报 vbstringdateintegervbscriptwindows (一)类型转换类函数1. CType( ...

  3. 页面加载完成后加载多个函数的js完美解决方案

    function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') ...

  4. iOS之NSString类中compare方法的陷阱

    typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDe ...

  5. cobbler 配置(转载)

    Cobbler介绍 Cobbler 是一个系统启动服务(boot server),可以通过网络启动(PXE)的方式用来快速安装.重装物理服务器和虚拟机,支持安装不同的 Linux 发行版和 Windo ...

  6. Java中创建对象的几种方式

    Java中创建对象的五种方式: 作为java开发者,我们每天创建很多对象,但是我们通常使用依赖注入的方式管理系统,比如:Spring去创建对象,然而这里有很多创建对象的方法:使用New关键字.使用Cl ...

  7. EQueue - 一个C#写的开源分布式消息队列的总体介绍

    前言 本文想介绍一下前段时间在写enode时,顺便实现的一个分布式消息队列equeue.这个消息队列的思想不是我想出来的,而是通过学习阿里的rocketmq后,自己用c#实现了一个轻量级的简单版本.一 ...

  8. 【转】一个lucene的官网例子

    创建索引: import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import jav ...

  9. angular controller as syntax vs scope

    今天要和大家分享的是angular从1.2版本开始带来了新语法Controller as.再次之前我们对于angular在view上的绑定都必须使用直接的scope对象,对于controller来说我 ...

  10. Unity3D手游开发实践

    <腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...