base php - yaokun123/php-wiki GitHub Wiki
为了更好的理解PHP7中zval的实现,我们先来了解下一些基本知识,包括数据类型,变量类型,与变量存储密切相关的堆栈等等基本知识
在c语言中,基本的数据类型有int,double,long,char以及指针ptr。c语言中,数据类型在不同系统中长度不同。
#include<stdio.h>
int main(){
printf("char sizeof = %d\n",sizeof(char)); //char sizeof = 1
printf("int sizeof = %d\n",sizeof(int)); //int sizeof = 4
printf("long sizeof = %d\n",sizeof(long)); //long sizeof = 8
printf("char * sizeof = %d\n",sizeof(char *)); //char * sizeof = 8
printf("void * sizeof = %d\n",sizeof(void *)); //void * sizeof = 8
return 0;
}
struct test{
char a; //1
int b; //4
long c; //8
void * d; //8
int e; //4
char * f; //8
}
从上面代码来看 整个结构体的大小是1+4+8+8+4+8=33?对吗? 下面来打印计算下:
printf("struct test sizeof = %d\n",sizeof(struct test)); //struct test sizeof = 40
从图上可以看到是40 而不是33,为什么呢?这就要引入另外一个概念,结构体对齐,在我的机器上是按照8自己来对齐的,如下图所示:
union test{
char a; //1
int b; //4
long c; //8
void * d; //8
}
printf("union test sizeof = %d\n",sizeof(union test)); //union test sizeof = 8
联合体是复用了同一块内存,对联合体的成员进行修改会影响其他成员的值,联合体的大小为其最大成员变量的大小。
-
栈区(stack):主要是存储参数、局部变量、维护函数调用关系
-
堆区(heap):动态内容区域,随时申请和释放
-
全局区:存储全局和静态变量
-
字面量区:常量字符串存储区
-
程序代码区:存储二进制代码
示意图如下:
PHP中的变量是弱类型的,也实现了如int,float,string,array和object等类型。PHP中的变量都是使用结构体zval表示的。下面我们先来了解下PHP5中的zval。
PHP5的zval(PHP5zval结构体 PHP-5.6.31/Zend/zend.h)
typedef union _zvalue_value {
long lval; /* long value 8字节*/
double dval; /* double value 8字节*/
struct {
char *val; //8字节
int len; //4字节
} str; //12字节
HashTable *ht; /* hash table value 8字节*/
zend_object_value obj; //12字节
zend_ast *ast; //8字节
} zvalue_value; //16字节
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value 16字节*/
zend_uint refcount__gc; //4字节,垃圾回收
zend_uchar type; /* active type 1字节*/
zend_uchar is_ref__gc; //1字节
};//24字节内存对齐
从上面来看,PHP5时代 对zval的优化都是通过结构映射的方式做的。
PHP7的zval
将下文分析