백엔드 개발 PHP 튜토리얼 【PHP内核学习】变量和数据类型

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

Jun 23, 2016 pm 01:57 PM
php 핵심 변하기 쉬운 공부하다 데이터 유형

          <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으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

CakePHP 프로젝트 구성 CakePHP 프로젝트 구성 Sep 10, 2024 pm 05:25 PM

이번 장에서는 CakePHP의 환경 변수, 일반 구성, 데이터베이스 구성, 이메일 구성에 대해 알아봅니다.

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 라우팅 CakePHP 라우팅 Sep 10, 2024 pm 05:25 PM

이번 장에서는 라우팅과 관련된 다음과 같은 주제를 학습하겠습니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 Dec 20, 2024 am 11:31 AM

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

See all articles