首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中的短路与算子优先

C中的短路与算子优先
EN

Stack Overflow用户
提问于 2020-05-12 11:49:55
回答 5查看 1K关注 0票数 8

我知道C中的逻辑运算符遵循短路,但我怀疑这是短路和运算符优先规则,而不是相互对立的。见下面的示例:

代码语言:javascript
复制
#include<stdio.h>
int main()
{
    int a;
    int b=5;

    a=0 && --b;
    printf("%d %d",a,b);

    return 0;
}

根据优先级规则,最高优先级是前缀操作符。因此,应该首先对--b进行评估,然后对&&进行评估,最后将结果分配给a。因此,预期的输出应该是0 4。但在这种情况下,&&的第二个操作数从未实际执行,其结果是0 5

为什么这里没有应用优先级规则。逻辑运算符是否不受优先规则的约束?如果是的话,还有什么其他经营者会表现出这种行为呢?这种行为背后的逻辑是什么?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2020-05-12 12:06:14

您合并了两个相关但不同的主题:运算符优先级和计算顺序。

运算符优先规则规定了如何将各种运算符组合在一起。在这种情况下:

代码语言:javascript
复制
 a=0 && --b;

操作人员按如下方式分组:

代码语言:javascript
复制
 a = (0 && (--b));

然而,这并没有影响操作数的计算顺序。&&运算符特别要求首先计算左操作数,如果其计算值为0,则不计算右操作数。

因此,在这种情况下,&&的左边是0,因为它是0,所以没有计算右侧的--b,所以b不会增加。

这里是另一个例子,说明了运算符优先级和求值顺序之间的区别。

代码语言:javascript
复制
int val()
{
    static x = 2;
    x *= 2;
    return x;
}

int main()
{
    int result = val() + (5 * val());
    printf("%d\n", result);
    return 0;
}

上面的程序会打印什么?事实证明,有两种可能性,两者都是有效的。

在这句话中:

代码语言:javascript
复制
val() + (5 * val())

没有任何操作人员具有任何类型的短路行为。因此编译器可以任意计算+*的各个操作数。

如果首先计算val()的第一个实例,结果将是4 + ( 5 * 8) == 44。如果首先计算val()的第二个实例,结果将是8 + (5 * 4) == 28。同样,这两个操作数都是有效的,因为操作数可以按任何顺序计算。

票数 8
EN

Stack Overflow用户

发布于 2020-05-12 12:03:07

优先级影响歧义表达式的解析方式。当有多种方法用几个运算符解释一个表达式时,优先级告诉我们哪种解释是正确的。将优先级看作一种机制,以确定隐含括号的位置。

例如,在所讨论的语句中,有两种有效的方法来解析它。如果=的优先级高于&&,则可以将其理解为:

代码语言:javascript
复制
(a = 0) && --b;

但是,由于&&具有更高的优先级,它实际上被解释为:

代码语言:javascript
复制
a = (0 && --b);

(注意:您的代码格式表明它是第一个。小心不要误导!)

求值顺序不同于优先级。它们是相关的,但独立的概念。在使用优先级来确定表达式的正确解析之后,计算顺序告诉我们计算操作数的顺序。从左到右吗?从右到左?同时?没有具体说明?

在大多数情况下,计算顺序仍未指定。像+*<<这样的运算符没有定义的计算顺序。编译器可以随心所欲地做任何事情,程序员不能编写依赖于任何特定顺序的代码。a + b可以计算a然后是b,或者b然后是a,或者甚至可以将它们的评估交织在一起。

除其他外,=&&是例外。=总是从右到左计算,而&&则是从左到右短路。

以下是我们的声明的评估进展情况:

  1. a = (0 && --b)=从右到左计算
    1. 0 && --b&&从左到右计算短路
      1. 0,计算触发短路的false,并取消下一步。
      2. --b,由于短路而未评估
      3. 结果是0

代码语言:javascript
复制
1. `a`, variable reference evaluated
2. `a = 0`, assignment occurs and overall result is `0`

您说过+*没有特定的顺序,但是这张桌子显示了从左到右的顺序。为什么会这样呢?

该表的最后一列是associativity.。当我们两次使用同一个运算符时,或者当我们使用具有相同优先级的运算符时,结合性就会打破优先级关系。

例如,我们应该如何阅读a / b / c。是:

  • (a / b) / c,或
  • a / (b / c)

根据表,/具有从左到右的结合性,所以它是第一个。

foo = bar = baz这样的链式作业呢?现在,赋值具有从右到左的相联性,所以正确的解析是foo = (bar = baz)

如果这一切都令人困惑,那么关注一个简单的经验法则:

“优先性和结合性与评价顺序无关。”

票数 7
EN

Stack Overflow用户

发布于 2020-05-12 11:59:21

operator &&的评价顺序从左到右。

=的优先级较低,实际上只有ooperator ,的优先级低于=

因此,在给定评价顺序的前提下,快速路将改为a = (0 && --b)为0。

由于0的计算结果为false,因此不需要计算表达式的第二部分,因为false && truefalse,如果表达式的第一部分是false,则表达式将始终是false

如果您有||操作符,则必须计算表达式的第二部分。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61750969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档