PHP语言中global和$GLOBALS[]的分析 之二


Posted in PHP onFebruary 02, 2012

还是借用上一篇的例子:

PHP代码

<?php 
// 例子1 
function test_global() { 
global $var1, $var2; 
$var2 =& $var1; 
} 
function test_globals() { 
$GLOBALS['var3'] =& $GLOBALS['var1']; 
} 
$var1 = 5; 
$var2 = $var3 = 0; 
test_global(); 
print $var2 .”\n”; 
test_globals(); 
print $var3 .”\n”; 
?>

执行结果为:
0
5
怎么会这样呢?不应该是2个5吗?怎么会出现1个0和1个5呢?

恩,我们保留以上问题,深入分析$GLOBALS和global的原理!
我们都知道变量其实是相应物理内存在代码中的”代号”而已
引用php手册的$GLOBALS的解释:
Global 变量:$GLOBALS,注意: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。
由所有已定义全局变量组成的数组。变量名就是该数组的索引。这是一个“superglobal”,或者可以描述为自动全局变量。
也就是说上面代码中的$var1和$GLOBALS['var1']是指的同一变量,而不是2个不同的变量!
下面来分析global到底做了什么?
引用php手册的global的解释:
如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。
我们都知道php中的函数所产生的变量都是函数的私有变量,那么global关键字产生的变量也肯定逃不出这个规则,为什么这么说呢,看下面的代码:
PHP代码

<?php 
// 例子2 
function test() { 
global $a; 
unset($a); 
} 
$a = 1; 
test(); 
print $a; 
?>

执行结果为:
1
为什么会输出1呢?不是已经把$a给unset了吗?unset失灵了?php的bug?
都不是,其实unset起作用了,是把test函数中的$a给unset掉了,可以在函数test()中加入
print $a;
来测试!
接着回到上面的例子1,看test_global中的这一代码“$var2 =& $var1;”,上面是一个引用赋值运算,也就是$var2将指向var1所指向的物理内存地址,所以例子1执行过test_global函数以后,变量的变化只在函数的局部产生效应,在函数外部$var2的指向物理内存地址并没有变化,还是它自己.
此时,就能理解为什么例子1执行完以后,$var2是0,而$var3是5了!
所以我们得出一个结论,在函数中global和$GLOBALS[]的区别在于:
global在函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,一但改变了别名变量的指向地址,就会发生一些意料不到情况,例如例子 1.
$GLOBALS[]确确实实调用是外部的变量,函数内外会始终保持一致
可以对照 下面两个列子再加深下印象:
global:
<?php 
function myfunction(){ 
global $bar; 
unset($bar); 
} 
$bar=”someting”; 
myfunction(); 
echo $bar; 
?>

输出:someting
$GLOBALS[]:
<?php 
function foo() 
{ 
unset($GLOBALS['bar']); 
} 
$bar = “something”; 
foo(); 
echo $bar; 
?>

输出:空
当按照上面的思路理解后,碰到下面的情况是不是又有些晕呢?
<?php 
$a = 1; 
$b = 2; 
function Sum() 
{ 
global $a, $b; 
$b = $a + $b; 
} 
Sum(); 
echo $b; 
?>

输出将是 “3″。在函数中申明 了全局变量 $a 和 $b,任何变量的所有引用变量都会指向到全局变量。
怎么不是2呢,在函数外部不是不影响吗,请注意$b在函数中并没有通过引用修改,而是修改的$b指向物理内存的值,因此外部输入为3。
PHP 相关文章推荐
使用apache模块rewrite_module (转)
Feb 14 PHP
比较详细PHP生成静态页面教程
Jan 10 PHP
php 保留字列表
Oct 04 PHP
PHP批量删除、清除UTF-8文件BOM头的代码实例
Apr 14 PHP
解决CodeIgniter伪静态失效
Jun 09 PHP
PHP中使用sleep造成mysql读取失败的案例和解决方法
Aug 21 PHP
php下载远程大文件(获取远程文件大小)的实例
Jun 17 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
Sep 21 PHP
详解php中生成标准uuid(guid)的方法
Apr 28 PHP
JS操作XML中DTD介绍及使用方法分析
Jul 04 PHP
php用wangeditor3实现图片上传功能
Aug 22 PHP
Yii 实现数据加密和解密
Mar 09 PHP
php中global和$GLOBALS[]的分析之一
Feb 02 #PHP
PHP开发者常犯的10个MySQL错误更正剖析
Jan 30 #PHP
PHP中全面阻止SQL注入式攻击分析小结
Jan 30 #PHP
几种有用的变型 PHP中循环语句的用法介绍
Jan 30 #PHP
通过PHP修改Linux或Unix口令的方法分享
Jan 30 #PHP
php代码收集表单内容并写入文件的代码
Jan 29 #PHP
php 无法加载mysql的module的时候的配置的解决方案引发的思考
Jan 27 #PHP
You might like
一步一步学习PHP(4) php 函数 补充2
2010/02/15 PHP
10个可以简化php开发过程的MySQL工具
2010/04/11 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
2012/07/20 PHP
php简单获取复选框值的方法
2016/05/11 PHP
php导出csv文件,可导出前导0实例代码
2016/11/16 PHP
PHPCMS手机站伪静态设置详细教程
2017/02/06 PHP
php7新特性的理解和比较总结
2019/04/14 PHP
php 实现简单的登录功能示例【基于thinkPHP框架】
2019/12/02 PHP
使用onbeforeunload属性后的副作用
2007/03/08 Javascript
解读IE和firefox下JScript和HREF的执行顺序
2008/01/12 Javascript
jQuery 核心函数以及jQuery对象
2010/03/23 Javascript
JS小功能(onmouseover实现选择月份)实例代码
2013/11/28 Javascript
JS+CSS实现的蓝色table选项卡效果
2015/10/08 Javascript
深入理解vue.js中的v-if和v-show
2017/06/22 Javascript
详解node nvm进行node多版本管理
2017/10/21 Javascript
ES6入门教程之let、const的使用方法
2019/04/13 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
跟老齐学Python之正规地说一句话
2014/09/28 Python
Python cookbook(字符串与文本)针对任意多的分隔符拆分字符串操作示例
2018/04/19 Python
在windows下Python打印彩色字体的方法
2018/05/15 Python
python requests指定出口ip的例子
2019/07/25 Python
使用 Python 合并多个格式一致的 Excel 文件(推荐)
2019/12/09 Python
TensorFlow加载模型时出错的解决方式
2020/02/06 Python
Python批量安装卸载1000个apk的方法
2020/04/10 Python
python如何更新包
2020/06/11 Python
Python同时处理多个异常的方法
2020/07/28 Python
css3学习心得分享
2013/08/19 HTML / CSS
深入浅析CSS3中的Flex布局整理
2020/04/27 HTML / CSS
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
小学防溺水制度
2014/01/29 职场文书
大学生个人求职口试自我评价
2014/02/16 职场文书
师恩难忘教学反思
2014/04/27 职场文书
担保贷款承诺书
2015/04/30 职场文书
创业计划书之韩国烧烤店
2019/09/19 职场文书
vue实现水波涟漪效果的点击反馈指令
2021/05/31 Vue.js