PHP变量的内存布局、实现方法以及作用域

前段时间用PHP开发了一个QQGame的后台发布系统(http://km.oa.com/post/167989),觉得使用PHP开发一些组内的工具是非常方便的。后来就打算把PHP了解的深入一点,要知道,C/C++程序员总是喜欢探究某语言底层的实现,难道是没被各类内存问题虐够?
想深入了解PHP的实现原理
,推荐一本书:《TIPI:深入理解PHP内核》;
看完之后,针对变量在PHP中如何存放,做了些总结和研究,
主要内容包括:PHP变量的内存布局,PHP弱类型的实现原理,PHP变量的类型和作用域等;

1.         PHP变量的内存布局

下图是变量在内存中的布局:

1.         PHP若类型的实现原理

PHP是一个弱类型、动态的脚本语言。弱类型是说PHP并不严格验证变量类型,在申明变量的时候不需要显示指明它保存的数据的类型。

动态脚本语言是说PHP的语言结构在运行期是可变的,例如我们在运行期require一个函数定义文件,会导致语言的函数表动态的改变。

大家都知道C/C++是强类型语言,即所有的变量在它被声明到最终销毁,都只能保存一种类型的数据。 PHP是如何在Zend引擎的基础上实现弱类型的呢?

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

其中zvalue_value是保存数据的关键部分,是个union体,定义如下:

PHP根据_zval_struct中的type字段来储存一个变量的真正类型,然后根据type来选择如何获取zvalue_value的值。其中,type支持的数据类型如下:

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

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

对于资源,Zend引擎会去取_zval_struct l.value.lval,此时的lval是个整型的指示器,然后PHP会再根据这个指示器在PHP内建的一个资源列表中查询相对应的资源。

借用这样的机制,PHP就实现了弱类型,因为对于Zend引擎来说,它所面对的永远都是同一种类型,即_zval_struct

2.         PHP变量的类型、作用域

变量的作用域:变量所起作用的范围;

大部分的 PHP 变量只有一个单独的范围。这个单独的范围跨度同样包含了 include require 引入的文件。

例如: 变量 $a 将会在包含文件 file2.inc.php 中生效,打印出100

a)         局部变量:

                                       i.              多数PHP变量都是局部变量,在其作用域外无法引用,并且超出其作用域时自动销毁。

                                     ii.              在当前文件主程序中定义的变量,其作用域限于当前文件的主程序,不能在其他文件或当前文件的局部函数中起作用。

                                    iii.              在局部函数中定义的变量仅限于当前函数,当前文件中主程序、其他函数、其他文件中无法引用。(这点和C/C++一致)

b)         全局变量:

                                       i.              PHP的全局变量和 C/C++稍有不同

                 1.         C/C++语言中,全局变量在函数中自动生效,除非被局部变量覆盖。

                  2.         PHP 中,在函数中使用全局变量时必须使用“global” $globals["变量名称"]关键字申明为全局,否则视为局部变量。

                                     ii.              php程序执行时,系统会在内存中保留一块全局变量的区域。(这点和C/C++一致)

                                    iii.              使用“global”关键字来申明全局数据的缺点:

全局数据把代码中原本单独的代码段都联系在一起了,这样的后果就是如果改变其中某一部分代码,可能就会导致其它部分出错。

            1.         代码重用几乎是不可能的

             如果一个函数依赖于全局变量,那么想在不同的环境中使用这个函数几乎是不可能的。另外一个问题就是你不能提取出这个函数,然后在其他的代码中使用。

            2.         调试并解决问题是非常困难的

               跟踪一个全局变量比跟踪一个非全局变量困难的多。

            3.         理解这些代码将是非常难的事情

               很难弄清楚一个全局变量是从哪里来,以及是用来做什么的。

c)  静态变量:

                                       i.              静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。

                                     ii.              静态作用域对递归函数很有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值