msgbartop
PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
msgbarbottom

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

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

<?php
  $var = 1; //int
  $var = "laruence"; //string
  $var = 1.0002; //float
  $var = array(); // array
  $var = new Exception('error'); //object;

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

  /usr/bin/php -f example.php

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

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

  • 深入浅出PHP(PHP Internals)
  • 深入理解PHP原理之Opcodes
  • 在PHP中,所有的变量都是用一个结构-zval来保存的, 在Zend/zend.h中我们可以看到zval的定义:

      typedef struct _zval_struct {
        zvalue_value value;
        zend_uint refcount;
        zend_uchar type;
        zend_uchar is_ref;
      } zval;
     

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

    typedef union _zvalue_value {
        long lval;
        double dval;
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;
        zend_object_value obj;
    } zvalue_value;
    

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

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

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

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

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

       zval.type = IS_STRING
    

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

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

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

       type = IS_RESOURCE
    

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

     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机制, 待续….


    分享到:



    Related Posts:

    Tags: , , ,

    39 Responses to “深入理解PHP原理之变量(Variables inside PHP)”

    1. hanuman chalisa with english translation |

      I get pleasure from, result in I found exactly whuat I was
      having a look for. You have ended myy 4 day longg hunt!
      God Bless you man. Have a nice day. Bye

    2. hanuman chalisa |

      What’s up mates, its enormous paragraph regarding educationand completely defined, keep it up all the
      time.

    3. 燕玉苗 |

      好文,PHP和C都学习了

    4. เครื่องพิมพ์เคสมือถือ |

      I read this post fully regarding the difference of most recent and preceding technologies, it’s awesome article.

    5. คลีนิคจัดฟัน พัทยา |

      A motivating discussion is definitely worth comment.
      I think that you ought to write more about this topic, it
      may not be a taboo matter but generally folks don’t discuss
      such issues. To the next! Best wishes!!

    6. descubre más |

      If you desire to increase your knowledge just keep visiting this web page and
      be updated with the latest news posted here.

    7. Dr Uday Tamhankar |

      Very rapidly this web site will be famous amid
      all blog users, due to it’s pleasant articles

    8. directory |

      What i do not realize is if truth be told
      how you’re no longer really a lot more well-favored than you might be
      now. You’re so intelligent. You know thus significantly on the subject
      of this topic, produced me in my view believe it from a lot of numerous angles.
      Its like women and men don’t seem to be fascinated except it
      is one thing to do with Woman gaga! Your own stuffs outstanding.
      All the time care for it up!

    9. เอมมูร่า |

      Hi, yup this post is really good and I have learned lot of things from it concerning blogging.
      thanks.

    10. ร้านสกรีนเสื้อ |

      Link exchange is nothing else but it is just placing the other person’s
      webpage link on your page at appropriate place and other person will also
      do similar for you.

    11. ประตูม้วน |

      Hurrah, that’s what I was seeking for, what a stuff!

      present here at this webpage, thanks admin of
      this web page.

    12. PHP 更高效的字符长度判断方法 | 玄午记 |

      [...] 晚上自己用例子简单测试下,情况基本属实,特此记录下。 后者效率几乎是前者的3倍。 具体原因是,在PHP中,所有的变量都是用一个结构-zval来保存的,strlen虽然是直接获取其中的len,但是仍然有一次函数调用,而isset是PHP的语法结构,所以更快! 示例: [...]

    13. Download Manager |

      Other reasons forr why AVG won’t install depend on thee
      error messages that you receive aand bewlow are some of thhe
      known reasoons why AVG installation will fail. But the carrier’s home
      page ( can help you find iit in a flash. 10 meanwhile offers the same image downloading features of thee
      Batch Images Downlkader extension ‘ and more.

    14. PHP 更高效的定长字符长度判断方法 | 玄午记 |

      [...] 晚上自己用例子简单测试下,情况基本属实,特此记录下。 后者效率几乎是前者的3倍。 具体原因是,在PHP中,所有的变量都是用一个结构-zval来保存的,strlen虽然是直接获取其中的len,但是仍然有一次函数调用,而isset是PHP的语法结构,所以更快! 示例: [...]

    15. (转)深入理解PHP原理之变量分离/引用(Variables Separation) - 码农@师帅 |

      [...] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之变量作用域(Scope inside PHP))。这节我们就接着前面的文章,继续介绍PHP中变量分离和引用的概念: [...]

    16. 深入理解PHP原理之变量分离/引用(Variables Separation) | Sheep's Blog |

      [...] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之变量作用域(Scope inside PHP))。这节我们就接着前面的文章,继续介绍PHP中变量分离和引用的概念: [...]

    17. 关于php内存的分配。 - 开发者问答 |

      [...] 了解了,关于变量下面两篇laruence文章有提到,特别是第二篇,个人觉得很好,真心建议坛友们多看看,估计很多人都看过了,挺出名的,再结合php官方那篇垃圾回收机制的文章,效果更好。变量存储http://www.laruence.com/2008/08/22/412.html变量分离引用http://www.laruence.com/2008/09/19/520.html [...]

    18. 深入了解php变量内核原理及变量内存管理系列文章 | pitaya's blog | 专注与LAMP很多年,Nginx,Linux,PHP,MySQL,Apache,Redis,Memcache,MongoDB,Oracle,Jquery,CentOS,Hadoop,weibo.com |

      [...] 2、深入理解PHP原理之Opcodes http://www.laruence.com/2008/06/18/221.html 3、深入理解PHP原理之变量(Variables inside PHP)  http://www.laruence.com/2008/08/22/412.html [...]

    19. 亚飞正传 |

      今天看到这篇,依然学到不少,谢谢。经典blog

    20. 写了个php简单扩展 |

      [...] 公司有个项目,有需要根据用户编号通过hash来计算用户下载记录所存储的数据库名和表名的算法,数据库用的是MySQL,下载记录的存储一共是100 * 100,也就是有100个库,每个库中有100张表,而具体的存储则是通过用户编号的hash计算出库名表名,然后将该用户的记录存储到相应表中,用户编号是字符串型的。原本这个算法C++部门已经实现了,按理没我什么事了,可是这回记录的读取要我们php这边去数据库直接读取,而为了计算个数据库和表的编号弄个接口似乎麻烦了,于是乎就把C++的该算法的逻辑发过来给我们php来实现。 原本以为很简单的事情,可是弄了之后问题来了,因为该算法中位运算使用的变量是unsigned long int型数据,而我们知道在php中所有的int型其实都是long int型的数据,都是有符号的,没有无符号长整型。关于php变量问题可以参见鸟哥的博文,PHP变量,这是网上别人转载的,鸟哥原文地址为 PHP变量,不过似乎暂时无法访问。 这时候就想到了PHP扩展,因为php扩展其实就是写c程序了,原先的C++的程序稍微改了一下也就可以通过gcc编译顺利运行了,代码如下: [...]

    21. 深入理解PHP原理之变量(Variables inside PHP) | warpig_allen's blog |

      [...] 本文地址: http://www.laruence.com/2008/08/22/412.html [...]

    22. 雪候鸟 |

      @Forever 不是结构体, 是union ;)

    23. Forever |

      照这样说每个变量占用的内存都比较大,因为它是结构体类型啊。结构体占用的内存不是所有类型加起来的嘛

    24. liano |

      牛人啊,我现在在学php能否给我个联系地址请教你一下啊?
      qq:584418561

    25. HorseLuke@微碌 » Blog Archive » php缓存扩展频繁存储/读取数组引发CPU过高问题排查手记(php-memcache为例) |

      [...] [2]laruence. 深入理解PHP原理之变量(Variables inside PHP):http://www.laruence.com/2008/08/22/412.html [...]

    26. 51nosql |

      向大牛学习,关注

    27. 关于引用的一个小问题。。。散分。。 - PHP常见问题 - [标签:tags] - 开源网 | 123Doing |

      [...] 如果你在php4和php5中分别执行上述代码,则php4 得到 21php5 得到 22 unset只是将$t指向的zval结构体的refcount – 1,然后清除符号表里的’t',去除$t与zval的关联但是$s仍然是关联zval的。我说不明白,有一篇高手写的文章专门讲这个的,在本坛我贴出来不少次了,你认真看看。http://www.laruence.com/2008/08/22/412.html 关键是这篇http://www.laruence.com/2008/09/19/520.html然后再结合php的GC原理会更深入一些。http://www.php.net/manual/en/features.gc.refcounting-basics.php [...]

    28. (转)深入理解PHP原理之变量分离/引用(Variables Separation) » Creative Power |

      [...] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之变量作用域(Scope inside PHP))。这节我们就接着前面的文章,继续介绍PHP中变量分离和引用的概念: [...]

    29. 关于引用的一个小问题。。。散分。。 - PHP常见问题 - 关于引用 一个小问题 散分 PHP 基础编程 - 123Doing |

      [...] unset只是将$t指向的zval结构体的refcount – 1,然后清除符号表里的’t',去除$t与zval的关联但是$s仍然是关联zval的。我说不明白,有一篇高手写的文章专门讲这个的,在本坛我贴出来不少次了,你认真看看。http://www.laruence.com/2008/08/22/412.html [...]

    30. 深入理解 PHP之require/include顺序 « 大熊猫 – konakona ——PHP程序员 |

      [...] 在PHP5中, 一个对象, 还是以一个zval做为载体的, 还记得什么是Zval么(深入理解 PHP原理之变量). [...]

    31. 深入理解PHP原理之对象(一) | 风雪之隅 |

      [...] 对象的结构 在PHP5中, 一个对象, 还是以一个zval做为载体的, 还记得什么是Zval么(深入理解PHP原理之变量). [...]

    32. Anonymous |

      牛人

    33. yzcj007 |

      感谢搂主,写得很棒,加油写,等着看呢!

    34. 完全COPY : 深入理解PHP原理之变量分离/引用(Variables Separation) |

      [...] Separation) 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之变量作用域(Scope inside [...]

    35. 狂笨地太阳 |

      太好了,终于理解PHP的变量是怎么个样子了。。PHP变量类型不同,ZVAL的TYPE就不同。

    36. 雪候鸟 |

      我指的Zend/zend.h是相当于PHP源码结构树的根目录
      比如,我看的是PHP5.2,那么Zend就是
      PHP5.2-SRC/Zend/

    37. bush |

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

      在php应用中 Zend相关的文件没有找到或见过 它属于哪一部分呢

    38. fj |

      mark

    39. 左手 |

      太佩服你了,强大的很

    Leave a Reply

    *