我知道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。
为什么这里没有应用优先级规则。逻辑运算符是否不受优先规则的约束?如果是的话,还有什么其他经营者会表现出这种行为呢?这种行为背后的逻辑是什么?
发布于 2020-05-12 12:06:14
您合并了两个相关但不同的主题:运算符优先级和计算顺序。
运算符优先规则规定了如何将各种运算符组合在一起。在这种情况下:
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("%d\n", result);
return 0;
}上面的程序会打印什么?事实证明,有两种可能性,两者都是有效的。
在这句话中:
val() + (5 * val())没有任何操作人员具有任何类型的短路行为。因此编译器可以任意计算+和*的各个操作数。
如果首先计算val()的第一个实例,结果将是4 + ( 5 * 8) == 44。如果首先计算val()的第二个实例,结果将是8 + (5 * 4) == 28。同样,这两个操作数都是有效的,因为操作数可以按任何顺序计算。
发布于 2020-05-12 12:03:07
优先级影响歧义表达式的解析方式。当有多种方法用几个运算符解释一个表达式时,优先级告诉我们哪种解释是正确的。将优先级看作一种机制,以确定隐含括号的位置。
例如,在所讨论的语句中,有两种有效的方法来解析它。如果=的优先级高于&&,则可以将其理解为:
(a = 0) && --b;但是,由于&&具有更高的优先级,它实际上被解释为:
a = (0 && --b);(注意:您的代码格式表明它是第一个。小心不要误导!)
求值顺序不同于优先级。它们是相关的,但独立的概念。在使用优先级来确定表达式的正确解析之后,计算顺序告诉我们计算操作数的顺序。从左到右吗?从右到左?同时?没有具体说明?
在大多数情况下,计算顺序仍未指定。像+、*和<<这样的运算符没有定义的计算顺序。编译器可以随心所欲地做任何事情,程序员不能编写依赖于任何特定顺序的代码。a + b可以计算a然后是b,或者b然后是a,或者甚至可以将它们的评估交织在一起。
除其他外,=和&&是例外。=总是从右到左计算,而&&则是从左到右短路。
以下是我们的声明的评估进展情况:
a = (0 && --b),=从右到左计算0 && --b,&&从左到右计算短路0,计算触发短路的false,并取消下一步。--b,由于短路而未评估0
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)。
如果这一切都令人困惑,那么关注一个简单的经验法则:
“优先性和结合性与评价顺序无关。”。
发布于 2020-05-12 11:59:21
operator &&的评价顺序从左到右。
=的优先级较低,实际上只有ooperator ,的优先级低于=。
因此,在给定评价顺序的前提下,快速路将改为a = (0 && --b)为0。
由于0的计算结果为false,因此不需要计算表达式的第二部分,因为false && true是false,如果表达式的第一部分是false,则表达式将始终是false。
如果您有||操作符,则必须计算表达式的第二部分。
https://stackoverflow.com/questions/61750969
复制相似问题