>  기사  >  백엔드 개발  >  【PHP内核学习】变量和数据类型

【PHP内核学习】变量和数据类型

WBOY
WBOY원래의
2016-06-23 13:57:361075검색

          <p class="sycode">              |=-----------------------------------------------------------------------=|          </p>          <p class="sycode">              |=---------------------=[ PHP内核中的变量和数据类型]=--------------------=|          </p>          <p class="sycode">              |=-----------------------------------------------------------------------=|          </p>          <p class="sycode">              |=--------------------------=[ by d4shman ]=-----------------------------=|          </p>          <p class="sycode">              |=-----------------------------------------------------------------------=|          </p>          <p class="sycode">              |=-------------------------=[  May 6, 2014  ]=---------------------------=|          </p>          <p class="sycode">              |=-----------------------------------------------------------------------=|          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              (_____ \| |   | (_____ \   /\   / _____) |  / )             </p>          <p class="sycode">               _____) ) |__ | |_____) ) /  \ | /     | | / /              </p>          <p class="sycode">              |  ____/|  __)| (_____ ( / /\ \| |     | |          </p><p class="sycode">              | |     | |   | |     | | |__| | \_____| | \ \              </p>          <p class="sycode">              |_|     |_|   |_|     |_|______|\______)_|  \_)   (向phrack致敬!)          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">                        </p>          <p class="sycode">              <br>          </p>          <p class="sycode">               0x01  变量的结构和类型          </p>          <p class="sycode">               0x02  哈希表--PHP的灵魂          </p>          <p class="sycode">               0x03  常量          </p>          <p class="sycode">               0x04  参考文献          </p>          <p class="sycode">                        </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              0x01  变量的结构和类型          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              1.数据类型          </p>          <p class="sycode">                1.1静态类型语言(C/Java),编译时确定          </p>          <p class="sycode">                1.2动态类型语言(php/python),运行时确定          </p>          <p class="sycode">                1.3无类型语言(汇编),操作的底层存储          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              2.php内核中所有的变量使用同一种数据结构zval来保存,而这个结构同时表示php中各种数据类型,它不仅仅包含变量的值,也包含变量的类型。这就是php弱类型的核心。          </p>          <p class="sycode">                      php中的8中数据类型:          </p>          <p class="sycode">                2.1标量类型: boolean, integer, float, string          </p>          <p class="sycode">                2.2复合类型:  array, object          </p>          <p class="sycode">                2.3特殊类型: resource, null          </p>          <p class="sycode">                          </p>          <p class="sycode">              3.zval结构体(在php源码目录下Zend/zend.h中定义):          </p>          <p class="sycode">                struct _zval_struct{          </p>          <p class="sycode">                	  /*Variable information*/          </p>          <p class="sycode">                	  zvalue_value value  	/*value, 变量的值*/          </p>          <p class="sycode">                	  zend_uint refcount__gc  /*reference count, 引用计数器*/          </p>          <p class="sycode">                	  zend_uchar type 		/*active type, 变量的类型*/          </p>          <p class="sycode">                	  zend_uchar is_ref__gc;  /*变量是否被引用*/          </p>          <p class="sycode">                }          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              4.变量类型:          </p>          <p class="sycode">                /*data types */          </p>          <p class="sycode">                #define IS_NULL		0           </p>          <p class="sycode">                #define IS_LONG 		1          </p>          <p class="sycode">                #define IS_DOUBLE 	2          </p>          <p class="sycode">                #define IS_BOOL 		3          </p>          <p class="sycode">                #define IS_ARRAY		4          </p>          <p class="sycode">                #define IS_OBJECT		5          </p>          <p class="sycode">                #define IS_STRING 	6          </p>          <p class="sycode">                #define IS_RESOURCE	7          </p>          <p class="sycode">                #define IS_CONSTANT	8          </p>          <p class="sycode">                #define IS_CONSTANT_ARRAY	9          </p>          <p class="sycode">                #define IS_CALLABLE	10          </p>          <p class="sycode">                          </p>          <p class="sycode">              5.变量的值存储          </p>          <p class="sycode">                typedef union _zvalue_value {          </p>          <p class="sycode">                    long lval; 		/*long、bool、resource类型*/          </p>          <p class="sycode">              	  double dval ;	/*double 类型*/          </p>          <p class="sycode">              	  struct {		/*string 类型, len保存了字符串的长度*/          </p>          <p class="sycode">              	  	char *val;          </p>          <p class="sycode">              	  	int len;          </p>          <p class="sycode">              	  } str;          </p>          <p class="sycode">              	  HashTable *ht;  /*数组, 用HashTable实现*/          </p>          <p class="sycode">              	  zend_object_value obj; /*object 类型*/          </p>          <p class="sycode">                } zvalue_value;          </p>          <p class="sycode">                          </p>          <p class="sycode">                这里之所以用共同体(union)是因为一个变量只可能有一种类型,符合共同体的特性,如果使用结构体则会浪费内存。          </p>          <p class="sycode">                          </p>          <p class="sycode">                实例:创建一个值为10的整型变量lvar,用php脚本的话很简单,就是:$lvar = 10          </p>          <p class="sycode">                而PHP内核中的实现可能就是类似下面这样:          </p>          <p class="sycode">                zval lval;          </p>          <p class="sycode">                Z_TYPE(lvar) = IS_LONG;          </p>          <p class="sycode">                Z_LVAL(lvar) = 10;          </p>          <p class="sycode">                          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              0x02  哈希表--PHP的灵魂          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              1.为什么用哈希表          </p>          <p class="sycode">                哈希表通常提供CRUD(Create, Read, Update, Delete)操作,设计合理的哈希表中,这些操作时间复杂度为O(1),这也是它被钟爱的原因。          </p>          <p class="sycode">                hash(key) -> index          </p>          <p class="sycode">                          </p>          <p class="sycode">              2.哈希表的实现:结构体 bucket和_hashtable组成了完整的HashTable。          </p>          <p class="sycode">                首先看bucket结构体(定义在 Zend/zend_hash.h):          </p>          <p class="sycode">                typedef struct bucket {          </p>          <p class="sycode">              	  ulong h;  					/*hash值*/          </p>          <p class="sycode">              	  uint nKeyLength;			/*key的长度*/          </p>          <p class="sycode">              	  void *pData;				/*要保存的内存块地址,通常是malloc来的地址*/          </p>          <p class="sycode">              	  void *pDataPtr;				/*保存指针数据,不经过malloc的指针,防止产生内存碎片*/          </p>          <p class="sycode">              	  struct bucket *pListNext;   /*bucket中具有同一hash值的下一个元素*/          </p>          <p class="sycode">              	  struct bucket *pListLast;   /*bucket中具有同一hash值的上一个元素*/          </p>          <p class="sycode">              	  struct bucket *pNext;		/*双向链表的下一个元素*/          </p>          <p class="sycode">              	  struct bucket *pLast;       /*双向链表的上一个元素*/          </p>          <p class="sycode">              	  const char *arKey;			/*保存key*/          </p>          <p class="sycode">                } Bucket;          </p>          <p class="sycode">                          </p>          <p class="sycode">                可以看出bucket是一个双向链表,这是为了解决多个key冲突的问题(即算法导论中的链接法)          </p>          <p class="sycode">                          </p>          <p class="sycode">                          </p>          <p class="sycode">                再看_hashtable结构体:          </p>          <p class="sycode">                typedef struct _hashtable {          </p>          <p class="sycode">                    uint nTableSize;                /*bucket数组的大小*/          </p>          <p class="sycode">              	  uint nTableMask;				          </p>          <p class="sycode">              	  uint nNumOfElements;			/*HashTable中元素的个数*/          </p>          <p class="sycode">              	  ulong nNextFreeElement;			/*下一个可用的Bucket位置*/          </p>          <p class="sycode">              	  Bucket *pInternalPointer		/*遍历HashTable元素*/          </p>          <p class="sycode">              	  Bucket *pListHead;				/*双向链表表头*/          </p>          <p class="sycode">              	  Bucket *pListTail;				/*双向链表表尾*/          </p>          <p class="sycode">              	  Bucket **arBuckets;				/*Bucket数组*/          </p>          <p class="sycode">                } HashTable;          </p>          <p class="sycode">                          </p>          <p class="sycode">                ========          </p>          <p class="sycode">                此处为HashTable的结构图          </p>          <p class="sycode">                ========          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              3.神奇的数字--33          </p>          <p class="sycode">                见我原来的一篇博客:http://blog.csdn.net/wusuopubupt/article/details/11479869          </p>          <p class="sycode">                下面是PHP源码中的一段注释:          </p>          <p class="sycode">                /*          </p>          <p class="sycode">                 * DJBX33A (Daniel J. Bernstein, Times 33 with Addition)          </p>          <p class="sycode">                 *          </p>          <p class="sycode">                 * This is Daniel J. Bernstein's popular `times 33' hash function as          </p>          <p class="sycode">                 * posted by him years ago on comp.lang.c. It basically uses a function          </p>          <p class="sycode">                 * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best          </p>          <p class="sycode">                 * known hash functions for strings. Because it is both computed very          </p>          <p class="sycode">                 * fast and distributes very well.          </p>          <p class="sycode">                 *          </p>          <p class="sycode">                 * The magic of number 33, i.e. why it works better than many other          </p>          <p class="sycode">                 * constants, prime or not, has never been adequately explained by          </p>          <p class="sycode">                 * anyone. So I try an explanation: if one experimentally tests all          </p>          <p class="sycode">                 * multipliers between 1 and 256 (as RSE did now) one detects that even          </p>          <p class="sycode">                 * numbers are not useable at all. The remaining 128 odd numbers          </p>          <p class="sycode">                 * (except for the number 1) work more or less all equally well. They          </p>          <p class="sycode">                 * all distribute in an acceptable way and this way fill a hash table          </p>          <p class="sycode">                 * with an average percent of approx. 86%.          </p>          <p class="sycode">                 *          </p>          <p class="sycode">                 * If one compares the Chi^2 values of the variants, the number 33 not          </p>          <p class="sycode">                 * even has the best value. But the number 33 and a few other equally          </p>          <p class="sycode">                 * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great          </p>          <p class="sycode">                 * advantage to the remaining numbers in the large set of possible          </p>          <p class="sycode">                 * multipliers: their multiply operation can be replaced by a faster          </p>          <p class="sycode">                 * operation based on just one shift plus either a single addition          </p>          <p class="sycode">                 * or subtraction operation. And because a hash function has to both          </p>          <p class="sycode">                 * distribute good _and_ has to be very fast to compute, those few          </p>          <p class="sycode">                 * numbers should be preferred and seems to be the reason why Daniel J.          </p>          <p class="sycode">                 * Bernstein also preferred it.          </p>          <p class="sycode">                 *          </p>          <p class="sycode">                 *          </p>          <p class="sycode">                 *                  -- Ralf S. Engelschall <rse>          </rse></p>          <p class="sycode">                 */          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">                          </p>          <p class="sycode">              4.哈希表的操作接口(省略了部分参数)          </p>          <p class="sycode">                初始化HashTable:int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction);          </p>          <p class="sycode">                添加新hash值:   int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData)          </p>          <p class="sycode">                查找hash:       int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              0x03  常量          </p>          <p class="sycode">              /////           </p>          <p class="sycode">              1.常量的内部结构          </p>          <p class="sycode">                typedef struct _zend_constant {          </p>          <p class="sycode">              	  zval value;          </p>          <p class="sycode">              	  int flags;  /*常量标记,如 CONST_PERSISTENT | CONST_CS */          </p>          <p class="sycode">              	  char *name;          </p>          <p class="sycode">              	  uint name_len;          </p>          <p class="sycode">              	  int module_number;          </p>          <p class="sycode">                } zend_constant;          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              2.define定义常量的过程            </p>          <p class="sycode">                define的实现(定义在Zend/zend_builtin_functions.c),下面是部分核心代码:          </p>          <p class="sycode">                          </p>          <p class="sycode">                ZEND_FUNCTION(define)          </p>          <p class="sycode">                {          </p>          <p class="sycode">                    /* 检查常量名是否存在 */          </p>          <p class="sycode">                    if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {          </p>          <p class="sycode">                        zend_error(E_WARNING, "Class constants cannot be defined or redefined");          </p>          <p class="sycode">                        RETURN_FALSE;          </p>          <p class="sycode">                    }          </p>          <p class="sycode">                              </p>          <p class="sycode">                    ... // 类常量定义 此处不做介绍          </p>          <p class="sycode">                              </p>          <p class="sycode">                    c.value = *val;          </p>          <p class="sycode">                    zval_copy_ctor(&c.value);          </p>          <p class="sycode">                    if (val_free) {          </p>          <p class="sycode">                            zval_ptr_dtor(&val_free);          </p>          <p class="sycode">                    }          </p>          <p class="sycode">                    c.flags = case_sensitive;  /* 大小写敏感 */          </p>          <p class="sycode">                    c.name = zend_strndup(name, name_len);          </p>          <p class="sycode">                    c.name_len = name_len+1;          </p>          <p class="sycode">                    c.module_number = PHP_USER_CONSTANT;          </p>          <p class="sycode">                    if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {  /*注册常量*/          </p>          <p class="sycode">                            RETURN_TRUE;          </p>          <p class="sycode">                    } else {          </p>          <p class="sycode">                            RETURN_FALSE;          </p>          <p class="sycode">                    }          </p>          <p class="sycode">                }          </p>          <p class="sycode">                          </p>          <p class="sycode">              3.魔术常量          </p>          <p class="sycode">                PHP中的魔术常量,虽然叫做常量,但它们的值实际上随它们在代码中的位置而变化的。          </p>          <p class="sycode">                __LINE__	 	文件中的当前行号。          </p>          <p class="sycode">                __FILE__	 	文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。          </p>          <p class="sycode">                __DIR__	 	文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于 dirname(__FILE__)。          </p>          <p class="sycode">                __FUNCTION__	函数名称          </p>          <p class="sycode">                __CLASS__	 	类的名称。类名包括其被声明的作用区域(例如 Foo\Bar)。          </p>          <p class="sycode">                __TRAIT__	 	Trait 的名字。Trait 名包括其被声明的作用区域(例如 Foo\Bar)。          </p>          <p class="sycode">                __METHOD__	类的方法名          </p>          <p class="sycode">                __NAMESPACE__	当前命名空间的名称(区分大小写)。此常量是在编译时定义的(PHP 5.3.0 新增)。          </p>          <p class="sycode">                          </p>          <p class="sycode">                PHP内核会在词法解析时将这些常量的内容赋值进行替换,而不是在运行时进行分析。 举个例子:          </p>          <p class="sycode">                <?php </p>          </p><p class="sycode">                echo __LINE__;          </p>          <p class="sycode">                function demo() {          </p>          <p class="sycode">                  echo __FUNCTION__;          </p>          <p class="sycode">                }          </p>          <p class="sycode">                demo();          </p>          <p class="sycode">                ?>          </p>          <p class="sycode">                PHP已经在词法解析时将这些常量换成了对应的值,以上的代码可以看成如下的PHP代码:          </p>          <p class="sycode">                <?php </p>          </p><p class="sycode">                echo 2;          </p>          <p class="sycode">                function demo() {          </p>          <p class="sycode">                    echo "demo";          </p>          <p class="sycode">                }          </p>          <p class="sycode">                demo();          </p>          <p class="sycode">                ?>          </p>          <p class="sycode">              <br>          </p>          <p class="sycode">                ===========          </p>          <p class="sycode">                此处涉及编译原理知识,需补充。          </p>          <p class="sycode">                ===========          </p>          <p class="sycode">                          </p>          <p class="sycode">              /////          </p>          <p class="sycode">              0x04  参考文献          </p>          <p class="sycode">              /////           </p>          <p class="sycode">              <br>          </p>          <p class="sycode">              TIPI: http://www.php-internals.com/book/?p=chapt03/03-00-variable-and-data-types          </p>
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.