文档章节

深入理解PHP原理之变量(Variables inside PHP)

botkenni
 botkenni
发布于 2018/06/08 16:58
字数 1017
阅读 2
收藏 0

或许你知道,或许你不知道,PHP是一个弱类型,动态的脚本语言。所谓弱类型,就是说PHP并不严格验证变量类型(严格来讲,PHP是一个中强类型语言,这部分内容会在以后的文章中叙述),在申明一个变量的时候,并不需要显示指明它保存的数据的类型:

 
  1. <?php
  2.   $var = 1; //int
  3.   $var = "laruence"; //string
  4.   $var = 1.0002; //float
  5.   $var = array(); // array
  6.   $var = new Exception('error'); //object;

动态语言,就是说,PHP的语言结构在运行期是可以改变的,比如我们在运行期require一个函数定义文件,从而导致语言的函数表动态的改变。
所谓脚本语言,就是说,PHP并不是独立运行的,要运行PHP我们需要PHP解析器:

 
  1.   /usr/bin/php -f example.php

我前面的文章中已经讲过,PHP的执行是通过Zend engine(ZE, Zend引擎), ZE是用C编写的,大家都知道C是一个强类型语言,也就是说,在C中所有的变量在它被声明到最终销毁,都只能保存一种类型的数据。 那么PHP是如何在ZE的基础上实现弱类型的呢?

首先要声明一点,如果你以前没有接触过PHP的源码分析,扩展开发。 如果你并不了解PHP的架构, 没有听说ZE,那么我建议你先看看我前面的文章,尤其推荐:

 

在PHP中,所有的变量都是用一个结构-zval来保存的, 在Zend/zend.h中我们可以看到zval的定义:

 
  1.   typedef struct _zval_struct {
  2.     zvalue_value value;
  3.     zend_uint refcount;
  4.     zend_uchar type;
  5.     zend_uchar is_ref;
  6.   } zval;
  7.  

其中zvalue_value是真正保存数据的关键部分,现在到了揭晓谜底的时候了,PHP是如何在ZE的基础上实现弱类型的呢? 因为zvalue_value是个联合体(union),

 
  1. typedef union _zvalue_value {
  2.     long lval;
  3.     double dval;
  4.     struct {
  5.         char *val;
  6.         int len;
  7.     } str;
  8.     HashTable *ht;
  9.     zend_object_value obj;
  10. } zvalue_value;

那么这个结构是如何储存PHP中的多种类型的呢?
PHP中常见的变量类型有:

 
  1. 1. 整型/浮点/长整型/bool值 等等
  2. 2. 字符串
  3. 3. 数组/关联数组
  4. 4. 对象
  5. 5. 资源
  6.  

PHP根据zval中的type字段来储存一个变量的真正类型,然后根据type来选择如何获取zvalue_value的值,比如对于整型和bool值:

 
  1.    zval.type = IS_LONG;//整形
  2.    zval.type = IS_BOOL;//布尔值

就去取zval.value.lval,对于bool值来说lval∈(0|1);
如果是双精度,或者float则会去取zval.value的dval。
而如果是字符串,那么:

 
  1.    zval.type = IS_STRING

这个时候,就会取:
zval.value.str
而这个也是个结构,存有C分格的字符串和字符串的长度。

而对于数组和对象,则type分别对应IS_ARRAY, IS_OBJECT, 相对应的则分别取zval.value.ht和obj

比较特别的是资源,在PHP中,资源是个很特别的变量,任何不属于PHP内建的变量类型的变量,都会被看作成资源来进行保存,比如,数据库句柄,打开的文件句柄等等。 对于资源:

 
  1.    type = IS_RESOURCE

这个时候,会去取zval.value.lval, 此时的lval是个整型的指示器, 然后PHP会再根据这个指示器在PHP内建的一个资源列表中查询相对应的资源(这部分的内容,我以后会单独开一个篇文章来介绍),目前,你只要知道此时的lval就好像是对应于资源链表的偏移值。

 
  1.  ZEND_FETCH_RESOURCE(con, type, zval *, default, resource_name, resource_type);

借用这样的机制,PHP就实现了弱类型,因为对于ZE的来说,它所面对的永远都是同一种类型,那就是zval。
ps:明天team出去building,我想着应该在走之前写点东西给我的blog reader来消磨周末。今天就简单先开个头,下一次,我将进一步介绍PHP的变量,作用域,以及变量的copy on write和change on write机制, 待续….

本文转载自:http://www.laruence.com/2008/08/22/412.html

共有 人打赏支持
botkenni
粉丝 20
博文 409
码字总数 434882
作品 0
西城
程序员
私信 提问
深入理解PHP原理之变量作用域(Scope in PHP)

我前面的文章(深入理解PHP原理之变量(Variables inside PHP))介绍了PHP变量的内部表示,但是,问题是,这些内部表示是如何和用户脚本中的变量联系起来的呢?也就是说,如果我在脚本中写下: ...

botkenni
2016/10/11
3
0
深入理解PHP原理之变量(Variables inside PHP)

或许你知道,或许你不知道,PHP是一个弱类型,动态的脚本语言。所谓弱类型,就是说PHP并不严格验证变量类型(严格来讲,PHP是一个中强类型语言,这部分内容会在以后的文章中叙述),在申明一个变...

晨曦之光
2012/03/09
214
0
PHP 一种访问私有属性的方法

在鸟哥《深入理解PHP原理之对象(一)》看到一段挺有意思的代码 <?phpclass Foo { }$foo = new Foo();$arr = (array) $foo;vardump($arr["0Foo0name"]);vardump($arr["0*0age"]);//output:str......

solu
2014/05/10
0
1
整理超级全局变量与全局变量的知识

全局变量就是在函数外面定义的变量。不能在函数中直接使用。因为它的作用域不会到函数内部。所以在函数内部使用的时候常常看到类似global $a; 超全局变量作用域在所有脚本都有效。所以,在函...

wangtaotao
2011/03/01
0
0
深入理解PHP原理之变量分离/引用(Variables Separation)

引自: http://www.laruence.com/ [风雪之隅 ] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之...

晨曦之光
2012/03/09
148
0

没有更多内容

加载失败,请刷新页面

加载更多

mybatis缓存的装饰器模式

一般在开发生产中,对于新需求的实现,我们一般会有两种方式来处理,一种是直接修改已有组件的代码,另一种是使用继承方式。第一种显然会破坏已有组件的稳定性。第二种,会导致大量子类的出现...

算法之名
昨天
12
0
单元测试

右键方法 Go To --> Test,简便快速生成测试方法。 相关注解 @RunWith(SpringRunner.class) 表示要在测试环境中跑,底层实现是 jUnit测试工具。 @SpringBootTest 表示启动整个 Spring工程 @A...

imbiao
昨天
3
0
欧拉公式

欧拉公式表达式 欧拉公式的几何意 cosθ + j sinθ 是个复数,实数部分也就是实部为 cosθ ,虚数部分也就是虚部为 j sinθ ,对应复平面单位圆上的一个点。 根据欧拉公式和这个点可以用 复指...

sharelocked
昨天
5
0
burpsuite无法抓取https数据包

1.将浏览器和burpsuite的代理都设置好 2.在浏览器地址栏输入: http://burp 3.下载下面的证书,并将证书导入浏览器 cacert.der

Frost729
昨天
3
0
JeeSite4.x 消息管理、消息推送、消息提醒

实现统一的消息推送接口,包含PC消息、短信消息、邮件消息、微信消息等,无需让所有开发者了解消息是怎么发送出去的,只需了解消息发送接口即可。 所有推送消息均通过 MsgPushUtils 工具类发...

ThinkGem
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部