短路和C中的操作员优先级



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

#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

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

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

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

a=0 && --b;

操作员分组如下:

a = (0 && (--b));

但是,这对操作数的求值顺序没有影响。特别是&&运算符规定首先对左操作数求值,如果求值为0,则不对右操作数求值。

因此,在这种情况下,&&的左侧(即0)被评估,并且因为它是0,所以右侧(即--b)不被评估,所以b不递增。

下面是运算符优先级和求值顺序之间差异的另一个示例。

int val()
{
static x = 2;
x *= 2;
return x;
}
int main()
{
int result = val() + (5 * val());
printf("%dn", result);
return 0;
}

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

在这个表达式中:

val() + (5 * val())

没有任何具有任何类型短路行为的操作员。因此编译器可以自由地按任何顺序计算+*的单个操作数。

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

优先级影响如何解析不明确的表达式。当有多种方法可以用几个运算符解释一个表达式时,优先级告诉我们哪种解释是正确的。将优先级视为一种机制,以确定隐含的括号在哪里。

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

(a = 0) && --b;

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

a = (0 && --b);

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

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

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

=&&等是例外。=总是从右到左进行评估,而&&是从左到右进行短路评估。

以下是我们声明的评估过程:

  1. a = (0 && --b)=从右到左评估
    1. 0 && --b&&通过短路从左到右进行评估
      1. 0,评估为false,触发短路并取消下一步
      2. --b,由于短路而未进行评估
      3. 结果为0
    2. a,评估的变量参考
    3. a = 0,分配发生,总结果为0

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

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

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

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

根据表/具有从左到右的关联性,因此它是第一个。

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

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

"优先级和关联性独立于评估顺序。">

运算符优先级并不一定表示表达式首先执行,它只是意味着对表达式进行解析,以便在较低优先级的运算中使用较高优先级运算的结果,而不是相反。实际表达式只有在需要时才进行求值!

operator &&的求值顺序是从左到右。

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

因此,在给定上述评估顺序的情况下,表达式将读取首先评估的a = (0 && --b)为0。

由于0的求值为false,因此不需要求值表达式的第二部分,因为false && truefalse,给定表达式的第一部分是false,则表达式将始终是false

如果使用||运算符,则必须对表达式的第二部分进行求值。

运算符优先级并不是游戏中的全部内容。还有评估的顺序。这要求首先评估a=0(评估顺序是从左到右),然后在&amp;根本不进行评估。

这就是C的工作原理。

相关内容

  • 没有找到相关文章

最新更新