PHP-$a 的值为什么是6呢

发布于 2017-02-01 21:20:38 字数 92 浏览 1357 评论 1

$a=1;
$b=&$a;
echo ++$a+ ++$a;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

虐人心 2017-10-22 05:29:54

你这个问题其实和 PHP中关于 &:引用符号的使用的问题--类似。

这里解释下原因吧,这是因为php存在"写时复制"的机制,具体"写时复制"是什么,可以来这里看看--PHP内核探索:写时复制COW机制

PHP对值的写时复制的操作,主要依赖于两个参数:refcount__gc 与 is_ref__gc。 如果是引用类型,则直接进行“分离”操作,即时分配内存,否则会写时复制,也就是在修改其值的时候才进行内存的重新分配。

其中 ++$a 的执行过程可以在源码的 php-5.3.20Zendzend_vm_execute.h 中第7717行找到,如下:

static int ZEND_FASTCALL  ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    // 省略 ...
    // 获取变量的地址
    zval **var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);

    // 省略 ...

    // 内存重新分配,也就是说结果的地址发生改变了
    // 第一次的++结果2和第二次++结果3的地址是不一样的,因此运算+的时候是2+3
    // 如果是引用的话,结果的最后地址是一致的,也就是实际变量的值
    // 第一次的++结果2和第二次++结果3的地址是一样的,这时就变成了3+3
    SEPARATE_ZVAL_IF_NOT_REF(var_ptr);

    if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
       && Z_OBJ_HANDLER_PP(var_ptr, set)) {
        // 省略 ...
    } else {
        // 自增内容
        increment_function(*var_ptr);
    }

    if (!RETURN_VALUE_UNUSED(&opline->result)) {
        AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
        PZVAL_LOCK(*var_ptr);
    }

    // 省略 ...
}

一个简单强制分离的例子

$a=1;
$b=&$a;
$d=0;
// 强制让$b和$a解除引用关系
echo ($b=&$d) + ++$a + ++$a; 
// 猜猜下面会是什么情况
// echo ++$a + ($b=&$d) + ++$a;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文