漫谈php全局变量Global
global语句的作用是定义全局变量,例如如果想在函数内访问全局作用域内的变量则可以通过global声明来定义。
下面从语法解释开始分析。
1. 词法解析
查看 Zend/zend_language_scanner.l文件,搜索 global关键字。我们可以找到如下代码:
<ST_IN_SCRIPTING>"global" {
return T_GLOBAL;
}
2. 语法解析
在词法解析完后,获得了token,此时通过这个token,我们去Zend/zend_language_parser.y文件中查找。找到相关代码如下:
| T_GLOBAL global_var_list ';'
global_var_list:
global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
| global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
;
上面代码中的$3是指global_var(如果不清楚yacc的语法,可以查阅yacc入门类的文章。)
从上面的代码可以知道,对于全局变量的声明调用的是zend_do_fetch_global_variable函数,查找此函数的实现在Zend/zend_compile.c文件。
void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC)
{
...//省略
opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->op1 = *varname;
SET_UNUSED(opline->op2);
opline->op2.u.EA.type = fetch_type;
result = opline->result;
... // 省略
fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
}
/* }}} */
上面的代码确认了opcode为ZEND_FETCH_W外,还执行了zend_do_assign_ref函数。zend_do_assign_ref函数的实现如下:
void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
{
zend_op *opline;
... //省略
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ASSIGN_REF;
...//省略
if (result) {
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
*result = opline->result;
} else {
/* SET_UNUSED(opline->result); */
opline->result.u.EA.type |= EXT_TYPE_UNUSED;
}
opline->op1 = *lvar;
opline->op2 = *rvar;
}
从上面的zend_do_fetch_global_variable函数和zend_do_assign_ref函数的实现可以看出, 使用global声明一个全局变量后,其执行了两步操作,ZEND_FETCH_W和ZEND_ASSIGN_REF。
3. 生成并执行中间代码
我们看下ZEND_FETCH_W的最后执行。从代码中我们可以知道:
- ZEND_FETCH_W = 83
- op->op1.op_type = 4
- op->op2.op_type = 0
而计算最后调用的方法在代码中的体现为:
zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];
计算,最后调用ZEND_FETCH_W_SPEC_CV_HANDLER函数。即
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
在zend_fetch_var_address_helper_SPEC_CV中调用如下代码获取符号表
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
在zend_get_target_symbol_table函数的实现如下:
static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
{
switch (opline->op2.u.EA.type) {
... // 省略
case ZEND_FETCH_GLOBAL:
case ZEND_FETCH_GLOBAL_LOCK:
return &EG(symbol_table);
break;
... // 省略
}
return NULL;
}
在前面语法分析过程中,程序传递的参数是 ZEND_FETCH_GLOBAL_LOCK,于是如上所示。我们取&EG(symbol_table);的值。这也是全局变量的存放位置。
如上就是整个global的解析过程。
漫谈php全局变量Global的更多相关文章
- php中全局变量global和超全局变量$GLOBALS
php中全局变量global和超全局变量$GLOBALS 1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require ...
- PHP中的全局变量global和$GLOBALS的区别
1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件. 但是在函数体内定义的global变量,函数体 ...
- python 局部变量和全局变量 global
当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是 局部 的.这称为变量的 作用域 .所有变量的作用域是它们被定义的块,从它们的名称被定义的那点开 ...
- CodeIgniter 定义“全局变量-global variable”,可以在所有controller,model和view中使用
本文抄自http://www.cnblogs.com/webu/archive/2012/11/20/2779999.html 第一次正儿八经用CodeIgniter框架做项目,结果不会定义全局变量, ...
- Python局部变量和全局变量global
当你在函数定义声明变量的时候,它们与函数外具有相同名称的其它变量没有任何关系,即变量名称对于函数来说是 局部 的.这称为变量的 作用域 .所有变量的作用域是它们被定义的块,从它们的名称被定义的那点开 ...
- 关于PHP中的全局变量global和$GLOBALS的不同区分
1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件. 但是在函数体内定义的global变量,函数体 ...
- PHP中全局变量global和$GLOBALS[]的区别分析
$GLOBALS['var']是外部的全局变量本身,global $var是外部$var的同名引用或者指针 一.举例比较 例一: 复制代码 代码如下: <?php $var1 = 1; ...
- php 中全局变量global 的使用
简介 即使开发一个新的大型PHP程序,你也不可避免的要使用到全局数据,因为有些数据是需要用到你的代码的不同部分的.一些常见的全局数据有:程序设定类.数 据库连接类.用户资料等等.有很多方法能够使这些数 ...
- 【PHP】- 全局变量global和$GLOBALS的区别
1.global global关键字的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件. 但是在函数体内定义的global变量, ...
随机推荐
- Roadblocks http://poj.org/problem?id=3255
Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best ...
- Android进阶笔记16:ListView篇之ListView刷新显示(全局 和 局部)
一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...
- XML 格式转JSON 格式
#import <Foundation/Foundation.h> #pragma GCC diagnostic push #pragma GCC diagnostic ignored & ...
- [Java]java反射随笔
类是面向对象的灵魂,一切事物都可以以类来抽象. 在java使用过程中,我们可能会经常用到一个反射的知识,只是别人都封装好的,如jdbc的加载驱动类有一句Class.for(“…jdbc…”).newI ...
- python(3)-计数器,有序字典
计数器:Counter 在使用计数器之前需要先 import collections >>> import collections >>> obj = collec ...
- javaweb学习总结一(eclipse常用快捷键、debug调试以及junit测试框架)
一:web的发展趋势1:C/S(客户端/服务器)结构向B/S(浏览器/服务器)结构发展,以后的电脑只需操作系统和浏览器即可.所有的服务都存储在服务器端,只需用户登录后从服务端同步数据,例如:看电影不需 ...
- Scala中的构造器和高阶函数
构造器 在定义类时可以定义主构造器.主构造器可以同时声明字段. /** * 主构造器 * @author Administrator */ //在scala中,类和方法交织在一起 class Test ...
- 理解Android系统的进程间通信原理(二)----RPC机制
理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI ...
- centos 安装ss-QT5
方法一(DNF指令): 1.如果未安装DNF,请跳转至:http://dev.fjuts.com:83/blog/index.PHP/Linux/261.html2.添加shadowsocks 的 c ...
- linux下svn命令常用操作
1.将文件checkout到本地目录 svn checkout path(path是服务器上的目录) 例如:svn checkout svn://192.168.1.1/pro/domain 简写:s ...