你会加法吗?我真是纠结了!求助,求解释
$a = 1;$c = $a + ($a++);var_dump($c);//3 $a = 1;$c = (++$a)+$a;var_dump($c);//4 $a = 1;$c = (++$a)+($a++);var_dump($c);//4 $a = 1;$b = &$a;$c = (++$a)+($a++);var_dump($c);//5
求解释。
回复讨论(解决方案)
1)表达式从左到右执行,所以$a这时还是1,1+2=3
2)同样是从左到右执行,++$a为2,这时$a已经自加过,所以2+2=4
3)++$a是先自加,这时$a值为2,后面的$a++是后自加,所以2+2=4
4)因为是改变引用的值,所以是2+3=5
$a = 1;
$c = $a + ($a++);
var_dump($c, $a);//3, 2
$a++ 等价于 $a = $a + 1
所以
$c = $a + ($a++);
等价于
$c = 2 + (1);
根据加法交换律
$c = $a + ($a++);
等价于
$c = ($a++) + $a; //写成这样就不难理解了吧?
等价于
$c = (1) + 2;
其他类同
1)表达式从左到右执行,所以$a这时还是1,1+2=3
2)同样是从左到右执行,++$a为2,这时$a已经自加过,所以2+2=4
3)++$a是先自加,这时$a值为2,后面的$a++是后自加,所以2+2=4
4)因为是改变引用的值,所以是2+3=5
求解释第三和第一的区别 既然是后自加 为甚么第一个不是2?
对于
$a = 1;
$c = (++$a)+($a++);
var_dump($c, $a);//4, 3
是这么理解的
(++$a) 先加 1,后取值
取出 $a 的值(2)参与运算
($a++) 先取值,后加 1
取出 $a 的值(2)参与运算
$c = (2) + (2)
虽然此时 $a 已经是 3 了
但参与计算的都是标量,没有变量
注意与 1 式的区别
xu大我还是不太理解和1式的区别 如果按照3式的分析,得到结果是2,当然这肯定是不对的 1式和3式的核心区别在哪里呢?....
$c = $a + ($a++);
是以变量参与运算的
xu大我还是不太理解和1式的区别 如果按照3式的分析,得到结果是2,当然这肯定是不对的 1式和3式的核心区别在哪里呢?....
++$a
表示$a先加1,再返回$a值
相当于
$a=$a+1;
返回 $a ;
$a++ 表示先返回$a的值再给$a加1
返回 $a;
$a=$a+1;
eg:
$a=1;
echo $a++; //先返回$a,然后给$a做加1运算 相当于 echo $a; $a=$a+1; 输出是1
echo ++$a; // 先给$a做加1运算,再返回$a 相当于 $a=$a+1; echo $a; 输出是2
xu大我还是不太理解和1式的区别 如果按照3式的分析,得到结果是2,当然这肯定是不对的 1式和3式的核心区别在哪里呢?.... 你也晕乎了是吧,哈哈哈
对于
$a = 1;
$c = (++$a)+($a++);
var_dump($c, $a);//4, 3
是这么理解的
(++$a) 先加 1,后取值
取出 $a 的值(2)参与运算
($a++) 先取值,后加 1
取出 $a 的值(2)参与运算
$c = (2) + (2)
虽然此时 $a 已经是 3 了
但参与计算的都是标量,没有变量
注意与 1 式的区别
综合斑竹两次的回答,第一个哈第三的解释,那就是说有括号的时候先运算括号内的,然后都转化为标量了再做计算是吧。
我还有疑惑,最后一个结果是5的是如何理解呢?
1)表达式从左到右执行,所以$a这时还是1,1+2=3
2)同样是从左到右执行,++$a为2,这时$a已经自加过,所以2+2=4
3)++$a是先自加,这时$a值为2,后面的$a++是后自加,所以2+2=4
4)因为是改变引用的值,所以是2+3=5
第一个好像就解释错了。
又无括号多没有关系,你这都是加法运算,由加法的结合律可知,无论是否有括号,括号加在哪里,都不会影响最终的结果
$a = 1;$c = (++$a)+($a++);var_dump($c);//4$a = 1;$c = ++$a + $a++;var_dump($c);//4$a = 1;$c = $a++ + ++$a;var_dump($c);//4
又无括号多没有关系,你这都是加法运算,由加法的结合律可知,无论是否有括号,括号加在哪里,都不会影响最终的结果
$a = 1;$c = (++$a)+($a++);var_dump($c);//4$a = 1;$c = ++$a + $a++;var_dump($c);//4$a = 1;$c = $a++ + ++$a;var_dump($c);//4那请问最后一个引用后变成5的那个怎么解释。
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5 不明白。还是有点晕。
反正执行过程中 $a++不影响$a的值,而是执行完毕才改变,类似for $i=...循环,$i在退出循环后值还要+1
++$a则是在执行过程中就改变了$a的值,执行后则不变
$b=&$a 导致了$a++做了“执行后”这个动作,所以$a++也递增了
我习惯就是这样理解的,也不知是否合适
$c = $a + ($a++);
是以变量参与运算的
xu大我还是不太理解和1式的区别 如果按照3式的分析,得到结果是2,当然这肯定是不对的 1式和3式的核心区别在哪里呢?....
$a=1;
$c= $a+($a++);
红色的$a是以变量参与运算,但是为什么是2呢? 难道$a+($a++)先运行($a++)部分吗?
测试过去掉$a++的括号结果还是一样,那么跟括号没有关系。那么表达式不是从左往右计算吗?
$c = $a + ($a++);
是以变量参与运算的
xu大我还是不太理解和1式的区别 如果按照3式的分析,得到结果是2,当然这肯定是不对的 1式和3式的核心区别在哪里呢?....
估计得这么理解
function returnFirst(&$a)
{
$return=$a;
$a=$a+1;
return $return;
}
function plusFirst(&$a)
{
$a=$a+1;
$return=$a;
return $return;
}
$a=1;
$c=$a+returnFirst($a) ; //$c=$a+(a++)
var_dump($c,$a); //3,2
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
那如果是
$c=($a++)+($a++) 要理解成 $c=($b=$a+1)+($b=$a+1)吗?
$c=($a++)+($a++) 返回的结果是3
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
那如果是
$c=($a++)+($a++) 要理解成 $c=($b=$a+1)+($b=$a+1)吗?
$c=($a++)+($a++) 返回的结果是3 更晕了,听了你的一席话,我又觉得斑竹的解释有问题了。。。
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
nnd这个问题太折磨人了
当$b=&$a,好像只有在(++$a)在运算表达式的最左边才会出意外的状况。
即:
(++$a)+表达式2+表达式3......
注:表达式为($a++)或者(++$a)
并且从第三个表达式开始都有的结果都有规律可寻,也就是说只会影响到(++$a)+表达式2的结果。
假设前n个表达式的和为Sn,运算完后$a=5;
则Sn+($a++)=Sn+5;
Sn+(++$a)=Sn+6
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
是不是php设计在这个问题上的设计缺陷哦。要是的话就很high哦,平生第一碰到这个级别的问题啊。
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
nnd这个问题太折磨人了
当$b=&$a,好像只有在(++$a)在运算表达式的最左边才会出意外的状况。
即:
(++$a)+表达式2+表达式3......
注:表达式为($a++)或者(++$a)
并且从第三个表达式开始都有的结果都有规律可寻,也就是说只会影响到(++$a)+表达式2的结果。
假设前n个表达式的和为Sn,运算完后$a=5;
则Sn+($a++)=Sn+5;
Sn+(++$a)=Sn+6
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
是不是php设计在这个问题上的设计缺陷哦。要是的话就很high哦,平生第一碰到这个级别的问题啊。 你也搞晕了?
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
nnd这个问题太折磨人了
当$b=&$a,好像只有在(++$a)在运算表达式的最左边才会出意外的状况。
即:
(++$a)+表达式2+表达式3......
注:表达式为($a++)或者(++$a)
并且从第三个表达式开始都有的结果都有规律可寻,也就是说只会影响到(++$a)+表达式2的结果。
假设前n个表达式的和为Sn,运算完后$a=5;
则Sn+($a++)=Sn+5;
Sn+(++$a)=Sn+6
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
是不是php设计在这个问题上的设计缺陷哦。要是的话就很high哦,平生第一碰到这个级别的问题啊。
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
这句话,说了等于没说。。你返回了半天,还是运算过后的$a的值,
对于
$a = 1;
$b = &$a;
var_dump($c);//5
由于应用的存在,情况要复杂点
由于有一个对 $b 的赋值过程,这相当于
$a = 1;
$c = (++$a)+($b = $a+1);
var_dump($c);//5
nnd这个问题太折磨人了
当$b=&$a,好像只有在(++$a)在运算表达式的最左边才会出意外的状况。
即:
(++$a)+表达式2+表达式3......
注:表达式为($a++)或者(++$a)
并且从第三个表达式开始都有的结果都有规律可寻,也就是说只会影响到(++$a)+表达式2的结果。
假设前n个表达式的和为Sn,运算完后$a=5;
则Sn+($a++)=Sn+5;
Sn+(++$a)=Sn+6
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
是不是php设计在这个问题上的设计缺陷哦。要是的话就很high哦,平生第一碰到这个级别的问题啊。
也就是符合把($a++) 当作 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; } 把(++$a)当作 function plusFirst(&$a){ $a=$a+1; return $a;}正确推算出来
这句话,说了等于没说。。你返回了半天,还是运算过后的$a的值,
我的意思是
$a = 1;
$c = $a + ($a++);
var_dump($c);//3
$a = 1;
$c = (++$a)+$a;
var_dump($c);//4
$a = 1;
$c = (++$a)+($a++);
var_dump($c);//4
第二种和第三种情况很好理解,就是单纯从左到右,并且符合对"先加后返回"或者"先返回后加"的理解
第一种情况呢,如果是从左边到右边运算的话,好像不符合对"先返回后加"的理解。但是如果是按照从右边到左边的运算顺序的话,就解释的通了。
我估计当运算式出现变量以及自加运算时,php会有个优先顺序,先运算自加的过程。
就好比
($a++)相当于 function returnFirst(&$a){ $return=$a; $a=$a+1; return $return ; }
(++$a)相当于 function plusFirst(&$a){ $a=$a+1; return $a;}
所以要是把($a++)替代成returnFirst(&$a),把(++$a)替代成plusFirst(&$a)
以上的三种情况都能解释得通。
但是,你列举了第四种情况,有变量引用
$a = 1;
$b = &$a;
$c = (++$a)+($a++);
var_dump($c);//5
注:
($a++)或者(++$a) 我称之为子表达式
若干个($a++)或者(++$a)相加 我称之为表达式
在有变量引用的时候,你用若干个($a++)和(++$a)相加时
只有当(++$a)在运算表达式的最左边才会出意外的状况(指的是出现与用函数替代不一致的结果),并且意外
只影响到(++$a)+“子表达式2”的结果。
也就是说,如果你已经知道(++$a)+“子表达式2”的结果,你还是可以用函数替代“子表达式2”之后的“子表达式”来推算结果。
综上所述,我认为($a++)可以用 returnFirst($a)来理解,(++$a)可以用 plusFirst($a)来理解。
第四种意外情况,可能是自加和引用同时出现时没有考虑到的php设计缺陷。当然这只是我猜测
C/C++和php的前加加后加加结果还不一样,php是通过zend内核来操作变量在内存中的分配,相比来说c/c++的还更好理解。
C/C++和php的前加加后加加结果还不一样,php是通过zend内核来操作变量在内存中的分配,相比来说c/c++的还更好理解。 请帮忙我们捋一捋吧。。。好理解的话。
看了楼上的各种解释,心里不免有很多疑问,总觉得每一种解释都很牵强。我觉得应该把它看作是php的一个bug,而不是一个特性。
用vld工具可以看到php的运算过程
第一步 ++$a 得出的表达式值我们用 $1表示。
第二步 $a++ 得出的表达式值我们用 $2表示。
第三步 计算 $1 + $2。
这个过程应该是没有异议的。
关键是 ++$a 的结果是什么?$a++的结果又是什么?
对于++$a, php用递增后的$a来表示表达式的结果, 也就是$1与$a在php的底层是指向同一个zval的。
而$a++呢, php先把$a复制出一份作为$2, 然后把$a加1, 也就是从此之后 $2与$a 不会再有半毛钱关系。
问题的关键就在 第二步的$a++改变了$a的值,而且由于$a是引用类型,此操作将不会在$a的副本上进行,这就会同步修改第一步的表达式值$1(因为$a和$1本来就是同一个东西)。
有兴趣的同学可以看下php的源码,在zend_vm_def.h中搜索PRE_INC即可找到 前置++ 的底层实现。 PRE_DEC也就是 前置-- 运算也有同样的问题。
明白了这些你就很容易构造出更多不符合预期结果的表达式
大家可以试一试
$a = 2;
$b = &$a;
echo ++$a + $a++;
echo ++$a + $a*=2;
echo --$a + $a--;
echo --$a - $a--;
echo ++$a + $a--;