C中的短路和运算符优先级

Nos*_*iii 7 c operators operator-precedence short-circuiting logical-operators

我知道 C 中的逻辑运算符遵循短路,但我怀疑短路和运算符优先级规则并不相互对立。请参阅以下示例:

#include<stdio.h>
int main()
{
    int a;
    int b=5;

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

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

根据优先级规则,最高优先级是前缀运算符。所以--b应该首先评估,然后&&最后的结果将被分配给a. 所以预期的输出应该是0 4. 但在这种情况下,第二个操作数&&never 实际执行并且结果是0 5.

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

dbu*_*ush 8

您将两个相关但不同的主题混为一谈:operator precedenceorder of evaluation

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

 a=0 && --b;
Run Code Online (Sandbox Code Playgroud)

运算符分组如下:

 a = (0 && (--b));
Run Code Online (Sandbox Code Playgroud)

然而,这对操作数的计算顺序没有影响。该&&运算符特别规定首先计算左操作数,如果计算结果为 0,则不计算右操作数。

所以在这种情况下,&&它的左侧是0被评估的,因为它是 0 右侧--b是不被评估的,所以b不会增加。

这是运算符优先级和计算顺序之间差异的另一个示例。

int val()
{
    static x = 2;
    x *= 2;
    return x;
}

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

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

在这个表达式中:

val() + (5 * val())
Run Code Online (Sandbox Code Playgroud)

没有任何运算符具有任何类型的短路行为。所以编译器就可以同时评估的各个操作数+,并*以任意顺序。

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


Joh*_*ica 7

优先级会影响歧义表达式的解析方式。当有多种方式来解释带有多个运算符的表达式时,优先级会告诉我们哪种解释是正确的。将优先级视为一种找出隐含括号位置的机制。

例如,在有问题的语句中,有两种有效的解析方法。如果=具有更高的优先级,&&则可以将其读作:

(a = 0) && --b;
Run Code Online (Sandbox Code Playgroud)

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

a = (0 && --b);
Run Code Online (Sandbox Code Playgroud)

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

评估顺序不同于优先级。它们是相关的,但独立的概念。在使用优先级确定表达式的正确解析之后,求值顺序告诉我们对操作数求值的顺序。是从左到右吗?右到左?同时?未指定?

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

=并且&&,除其他外,是例外。=总是从右到左求值,&&短路时从左到右求值。

以下是我们语句的评估如何逐步进行:

  1. a = (0 && --b),=从右到左计算
    1. 0 && --b,&&从左到右评估短路
      1. 0, 评估 false 触发短路并取消下一步
      2. --b, 因短路未评估
      3. 结果是 0
    2. a, 评估变量引用
    3. a = 0,分配发生,总体结果是 0

你说+and没有特定的顺序*,但是这个表显示的顺序是从左到右。为什么这样?

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

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

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

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

链式作业怎么样foo = bar = baz?现在,赋值具有从右到左的结合性,因此正确的解析是foo = (bar = baz)

如果这一切都变得令人困惑,请关注一个简​​单的经验法则:

“优先级和关联性与评估顺序无关。”