千家信息网

PHP变量的存储过程源码分析

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"PHP变量的存储过程源码分析",在日常操作中,相信很多人在PHP变量的存储过程源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PHP变量的存储过
千家信息网最后更新 2026年11月02日PHP变量的存储过程源码分析

这篇文章主要介绍"PHP变量的存储过程源码分析",在日常操作中,相信很多人在PHP变量的存储过程源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PHP变量的存储过程源码分析"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

PHP代码如下:

复制代码 代码如下:

$php_var = 1;

对应C的代码是:

复制代码 代码如下:

zval* c_var; //定义PHP变量指针
MAKE_STD_ZVAL(c_var); //初始化PHP变量
ZVAL_LONG(c_var,1) ;//赋值
ZEND_SET_SYMBL( EG(active_symbol_table), " php_var ", c_var);//注册到全局变量符号表

一.首先看第一行: zval* c_var;//申明一个zval指针c_var; zval的结构如下:

复制代码 代码如下:


struct _zval_struct {
/* Variable information */
zvalue_value value; /* 变量的值 */
zend_uint refcount; /* 引用计数,垃圾回收的时候用到 */
zend_uchar type; /* 变量类型 */
zend_uchar is_ref; /* 是否为引用变量 */
};
typedef struct _zval_struct zval;

其中值zvalue_value的结构如下:

复制代码 代码如下:


typedef union _zvalue_value {
long lval; /* 长整形*/
double dval; /* 双精度类型 */
struct { /* 字符串类型的值 */
char *val;
int len;
} str;
HashTable *ht; /* 数组类型的值 */
zend_object_value obj; /*对象类型的值*/
} zvalue_value;

二.接下来看第二行: MAKE_STD_ZVAL(new_val);//变量初始化 相关宏如下: //初始化

复制代码 代码如下:


#define MAKE_STD_ZVAL(zv) \
ALLOC_ZVAL(zv); \
INIT_PZVAL(zv);

#define ALLOC_ZVAL(z) \
ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)

#define ZEND_FAST_ALLOC(p, type, fc_type) \
(p) = (type *) emalloc(sizeof(type))

#define INIT_PZVAL(z) \
(z)->refcount = 1; \
(z)->is_ref = 0;


展开后为:

复制代码 代码如下:


(c_var) = (zval *) emalloc(sizeof(zval)); //分配内存
(c_var)-> refcount = 1; //引用计数初始化
(c_var)-> is_ref = 0; //是否引用

可以看到其作用就是分配内存,初始化refcount,is_ref

三.下面看第三行 ZVAL_LONG(c_var,1) 相关宏为:

复制代码 代码如下:


//定义值
#define ZVAL_LONG(z, l) { \
Z_TYPE_P(z) = IS_LONG; \
Z_LVAL_P(z) = l; \
}
#define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
#define Z_TYPE(zval) (zval).type
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
#define Z_LVAL(zval) (zval).value.lval

展开后为:

复制代码 代码如下:


(* c_var).type = IS_LONG;
(* c_var).value = 1;

四:接下来看第四行: ZEND_SET_SYMBOL( EG(active_symbol_table), "php_var", c_var); 首先说明下PHP的变量是存在一个hashtable里的

复制代码 代码如下:


struct _zend_executor_globals {
….
HashTable symbol_table;//全局变量的符号表
HashTable *active_symbol_table;//局部变量的符号表
…..
};

Hashtable的Key为变量的名称,即php_var,值为指向PHP变量的指针,即c_var指针; 相关宏为:

复制代码 代码如下:


#define ZEND_SET_SYMBOL(symtable, name, var) \ { \
char *_name = (name); \
ZEND_SET_SYMBOL_WITH_LENGTH(symtable, _name, strlen(_name)+1, var, 1, 0); \
}
//主要的实现为下面这个函数:
#define ZEND_SET_SYMBOL_WITH_LENGTH(symtable, name, name_length, var, _refcount, _is_ref) \
{
zval **orig_var; \
if (zend_hash_find(symtable, (name), (name_length), (void **) &orig_var)==SUCCESS \
&& PZVAL_IS_REF(*orig_var)) { \
(var)->refcount = (*orig_var)->refcount; \
(var)->is_ref = 1; \
if (_refcount) { \
(var)->refcount += _refcount-1; \
} \
zval_dtor(*orig_var); \
**orig_var = *(var); \
FREE_ZVAL(var); \
} else { \
(var)->is_ref = _is_ref; \
if (_refcount) { \
(var)->refcount = _refcount; \
} \
zend_hash_update(symtable, (name), (name_length), &(var), sizeof(zval *), NULL); \
} \
}

该函数的功能是:
1. 如果全局符号表已经存在该变量且是引用类型,则

a. 将原来变量的引用计数refcount,is_ref信息赋给c_var;
b. 释放掉原来变量zvalue的值,比如原来其值指向的是一个mysql连接资源,则释放该资源。
c. 将c_var指向的变量赋值给原来的变量 d. 释放c_var的内存空间 这样保证了,如果变量被应用,值一起改变。比如如果前面有$b=&a;

2. 如果全局符号表不存在该变量或者存在该变量但不是引用变量,则直接改变其值。

到此,关于"PHP变量的存储过程源码分析"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

变量 代码 类型 符号 源码 过程 分析 存储 全局 指针 学习 内存 指向 函数 更多 结构 资源 分配 帮助 实用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 南京欣网互联网络科技 互联网科技产业 互联网络科技有限公司 互联网科技集团 安徽鑫晟辉互联网科技 南京欣网互联网科技 新浪科技互联网 郑州华宇互联网科技 互联网金融科技委员会 太原新华互联网科技学校怎么样 中国科技互联网公司收入 成都铂石互联网科技做什么的 武汉健翔互联网络科技有限公司 玉溪互联网科技怎么选 佛山市拉法互联网科技有限公司 山东子淼互联网科技有限公司 杭州披云加互联网科技有限公司 江苏互联网科技小贷 互联网科技手抄报图片 安徽零酒互联网科技有限公司 蓝思科技飞鸽互联网 远拓互联网科技 互联网女皇 腾讯科技 睿民互联网科技 中国最先进互联网科技公司 老年人脱离互联网科技的作文 江苏南京365互联网科技 中国航天科技大学国际工业互联网 东莞新华互联网科技学校 广东猫王互联网科技有限公司电话
0