变量的类型(8种)
四标量:int float string boolean
两复合:array object
两特殊类型:resource NULL变量的定义
php是弱类型的语言,意味着不用强制申明该变量的类型就可以使用可用。是动态的语言,说明在运行周期内require 一个文件是会引起函数表动态的改变。
强类型语言
int iNum = 1;
string strNum = '1';
php语言
$num = 1;
$num = '1';
- Zend Engine
讨论php变量在内存中的存储之前,理解Zend引擎(Zend Engine)的作用和含义。区分下zend studio,zend studio 是zend 公司开发的一款php的集成开发环境。zend 公司是由开源PHP的缔造者和建筑师Zeev Suraski and Andi Gutmans共同创建。 - Zend Engine 引擎的来历参考这篇文章
现在基本都是用的是>= php 5.0 的版本。而在php3.0之前php的运行方式还是边解释边运行.运行效率很受其影响,代码耦合度高,可扩展性也不够好,不利于应付各种各样需求。为此,Zeev Suraski 和 Andi Gutmans 决定重写代码以解决这两个问题,把该项技术的核心引擎命名为 Zend Engine,
- zend Engine的作用
PHP实现的核心,提供了语言实现上的基础设施,例如:PHP的语法实现,脚本的编译运行环境, 扩展机制以及内存管理等。(主要特性:Zend 就是把 PHP 的边解释边执行的运行方式改为先进行预编译(Compile),然后再执行(Execute)。)
- zend Engine的作用
- 变量在内核中的存储方式
php是弱类型语言。这代表着一个变量可以保存任何的数据类型。而php是使用C语言编写的。而C语言是强类型语言(每个变量都有其固定的类型).那么在Zend 引擎中是这样做到一个变量可以保存任何的数据类型的。
zend/zend.h 头文件中的结构体
typedef struct_zval_struct zval;
typedef union_zvalue_value {
long lval;
double dval;
struct{
char*val;
int len;
}str;
Hashlable *ht;
zend_object_value obj
}zvalue_value;
struct_zval_struct{
zvalue_value value; //变量的值(一个zvalue_value联合体)
zend_uint refcount_gc; //变量引用数
zend_uchar type; //变量的类型
zend_uchar is_ref_gc; //是否被引用
};
zval 结构体就是php变量在内核中的表示方式。可以看啊zvalue_value联合体中定义了各种数据类型。不同的类型就会保存到不同的成员变量中,这样就实现了php变量可以存储任何的数据类型。
那么又是如何识别各种数据类型的呢?
- zend引擎定义了几种变量类型,
#define IS_NULL 0
#define IS_LONG 1
#define IS_DUBLE 2
#define IS_STRING 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_BOOL 6
#define IS_RESOURCE 7
关注下 array 其实对应了Hashtable(将键映射到相对应的值上)。
- 引用计数器
PHP是不足支持指针的,但又希望俩个变量同时指向同一块内存。就用了引用计数器解决这个问题。(注:参考主人ohmygirl的这篇文章PHP内核探索之变量(1)变量的容器-Zval)
$a = 1;
$b = $a;
这里 变量 a和变量 b 共享同一份zval容器;容器的refcount_gc ++;当增减引用时,这个值也相应的递增和递减,一旦减到零,Zend就会回收该zval。那么这个时候就有必要了解写时复制;当多个变量同时指向一个zval容器,而要修改其中一个变量的时候,就会单独为这个变量创建一个新的zval容器。
- 变量的释放
其实看了很多的文章.很肯定的一点是unset()是有作用的,只是对于PHP的回收机制来说,会有多种情况.
情况1:
$a = 1;
unset($a); // 内存是有释放的
情况2:
$a = 1;
$b = $a;
unset($a); // 由引用计数器可知,这时候 refcount_gc 只是减一,那么实际上refcount_gc=1
// refcount_gc>0 的所以zval容器并没有被注销。
那为什么 循环申明变量和循环销毁变量,内存却不会是原来的大小呢。可以参考鸟叔的文章:深入理解PHP内存管理之谁动了我的内存
- php HashTable
前面归纳的是变量类型、定义和zval的关系。那么每一个变量是如何和zval联系起来呢,可以参考博主orlion的PHP变量在内存中的存储方式
大概为:变量存储在一个相当于关联数组的 符号表中。这个数组以变量名为key,并且指向包含了这些变量的容器.unset变量的时候 应该是先根据这个符号表找到对应的zval ,refcount_gc –.判断,refcount_gc 是否大于0,再决定是否销毁zval。可以肯定的是符号表中$a的键名是肯定删掉了。