今天群里有个人问了一个问题,代码如下:
$a = 3;
$b = 2;
if ($a = 2 || $b = 5) {
    ++$a;
}
echo $a;
说代码段的执行的结果为1,问大家$a的值为什么不是3。
我看到这段代码后,和提问者的想法一样,也以为$a的值应该是3。
然后就有人说了,因为 | | 的优先级高于 = ,所以($a = 2 || $b = 5)应该写成($a = ( 2 || $b = 5)),
( 2 || $b = 5)的“或”运算结果为True,将它赋值给变量a,所以$a的值为1。
 
兴趣上来后,我就顺手打印了一下变量b的值,发现变量b的值为2。为什么变量b没有被赋值呢?有人提出了一个概念叫“短路求值”。
“短路求值”的定义如下:
作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值(short-circuit evaluation)。
假如expr1和expr2都是表达式,expr2是否求值视expr1而定:
expr1 || expr2:
    expr1的值为1,则expr2将不会进行求值。
expr1 && expr2:
    expr1的值为0,则expr2将不会进行求值。
因为( 2 || $b = 5)中,先进行2的“或”运算,结果为真,则 | | 后面$b = 5的赋值操作就不再执行了。
 
如果将 | | 前面的 2 改成 0:
$a = 3;
$b = 2;
if ($a = 0 || $b = 5) {
    echo $b;    // 5
}
echo $a;    // 1
$b的值就是5了,因为 0 的“或”运算结果为假,则后面会将5赋值给变量b,又因为“或”运算是只要两个表达式有一个为真,其结果就为真,所以$a的值仍为1。
 
那么,再将 | | 改成 &&:
$a = 3;
$b = 2;
if ($a = 0 && $b = 5) {
    var_dump($b);    // &&后面对b的赋值操作不进行,所以无输出
}
var_dump($a);    // false
echo $b;        // 2
因为0 的“与”运算结果为假,则&&后面不会再将5赋值给变量b,
又因为“与”运算是只要两个表达式有一个为假,其结果就为假,所以$a的值为0。
 
题外话:这道题虽然看起来很简单,但是经过群里“吃瓜群众”的讨论和讲解,我收获很多。尤其是我在群里说“明白了”后,那个提问者还加了我微信,和我探讨。非常佩服对方的钻研精神,如果我将这种钻研精神用到工作和学习中,想必进展一定会大大的。还要更努力哟~

一道PHP题引出的“短路求值”的更多相关文章

  1. 一个短路求值引起的一个小bug

    今天在写一个判断字符串是否回文时因为短路求值问题导致了一个bug,记录如下: 代码如下 bool isPal(char str[],int len) { int begin=0; int end=le ...

  2. C 语言 - 逻辑运算和短路求值

    逻辑运算符: 运算符 含义 优先级 ! 逻辑非 高 && 逻辑与 中 || 逻辑或 低 举例: !a:如果 a 为真,!a 为假:如果 a 为 假,!a 为真 a && ...

  3. Julia - 短路求值

    && 和 || 的布尔运算符被称为短路求值 它们连接一系列布尔表达式,仅计算最少的表达式来确定整个链的布尔值 在表达式 a && b 中,只有 a 为 true 时才计 ...

  4. php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干)

    php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干) 一.总结 1.仔细分析题干,找出要点:该递归还是得递归啊 2.短路求值原理:&&就是逻辑与,逻辑与有 ...

  5. js 实用技巧 短路求值

    &&运算符  如果操作有false  则返回false  例如 0&&1  // 返回0 true&&false  //返回false 0&&a ...

  6. 【python】Leetcode每日一题-逆波兰表达式求值

    [python]Leetcode每日一题-逆波兰表达式求值 [题目描述] 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说 ...

  7. “短路求值(Short-Circuit Evaluation)

        // 逻辑与和逻辑或操作符总是先计算其做操作数,只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数. function aa() { if (null) { console ...

  8. Matrix Chain Multiplication(表达式求值用栈操作)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1082 Matrix Chain Multiplication Time Limit: 2000/100 ...

  9. C语言对表达式的求值顺序不是明确规定的

    讨论区看到的 WA来自那些递归下降求解的代码. 第一种情况,使用|| 和 &&: 例如s为所给串 int getval() { switch(s[c_s++]) { case 'p': ...

随机推荐

  1. vs添加webservice

    VS2010中添加WebService注意的几个地方 添加web引用和添加服务引用有什么区别? 2.4.1 基础知识——添加服务引用与Web引用的区别 C#之VS2010开发Web Service V ...

  2. 【译】第21节---Fluent API

    原文:http://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx 在前面的学习中.我们已经看到不同的 ...

  3. python学习 day09打卡 初识函数

    本节内容: 1.什么是函数 2.函数定义,函数名,函数体及函数的调用 3.函数的返回值 4.函数的参数 一.什么是函数 函数:对代码块和功能的封装和定义 定义一个事情或者功能.等到需要的时候直接去用, ...

  4. 在用node安装某个全局模块的时候,没有权限修改node_modules

    一.问题 今天在安装公司内部的一个npm模块的时候,发现报错了⬇ 第一行错误: deprecated graceful-fs@1.2.3: please upgrade to graceful-fs ...

  5. codeforces gym 101164 K Cutting 字符串hash

    题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #prag ...

  6. ORA-03113: end-of-file on communication channel(归档满处理方法)

    归档放在flash_recovery目录,由于归档占满了闪回目录,数据库启动报错ORA-03113: end-of-file on communication channel tail -1200f ...

  7. @Scope注解设置创建bean的方式和生命周期

    1.1.1            Scope注解创建bean的方式和生命周期 作用 Scope设置对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式. 取 ...

  8. Cocos Creator 脚本模板

    1.由于新建Cocos Creator脚本带有很多注释,并且有时候需要增加定制的默认注释,所以需要修改脚本生成模板. 2.在CocosCreator\resources\static\template ...

  9. ubuntu18+gtx1060 +cuda9+cudnn-v7+opencv3.1.0 配置深度学习环境

    将笔记本的ubuntu系统更新到18版本后重新配置深度学习环境,在此记载方便日后参考 具体配置为 Ubuntu18.04+gtx1060+opencv-3.1 第1步 安装依赖包 sudo apt-g ...

  10. AtCoder Regular Contest 103 E Tr/ee

    Tr/ee 思路:按照下图所示连接 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #inclu ...