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.
为什么这里没有应用优先规则。逻辑运算符是否不受优先规则的约束?如果是,还有哪些其他运营商表现出这种行为?这种行为背后的逻辑是什么?
您将两个相关但不同的主题混为一谈:operator precedence和order 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。同样,两者都是有效的,因为可以以任何顺序评估操作数。
优先级会影响歧义表达式的解析方式。当有多种方式来解释带有多个运算符的表达式时,优先级会告诉我们哪种解释是正确的。将优先级视为一种找出隐含括号位置的机制。
例如,在有问题的语句中,有两种有效的解析方法。如果=具有更高的优先级,&&则可以将其读作:
(a = 0) && --b;
Run Code Online (Sandbox Code Playgroud)
但由于&&具有更高的优先级,它实际上被解释为:
a = (0 && --b);
Run Code Online (Sandbox Code Playgroud)
(注意:您的代码格式表明它是第一个。小心不要误导!)
评估顺序不同于优先级。它们是相关的,但独立的概念。在使用优先级确定表达式的正确解析之后,求值顺序告诉我们对操作数求值的顺序。是从左到右吗?右到左?同时?未指定?
大多数情况下,评估顺序未指定。像+和*和<<这样的运算符没有定义的计算顺序。编译器可以为所欲为,程序员不得编写依赖于任何特定顺序的代码。a + b可以评估athen b,或者bthen a,或者甚至可以将它们的评估交织在一起。
=并且&&,除其他外,是例外。=总是从右到左求值,&&短路时从左到右求值。
以下是我们语句的评估如何逐步进行:
a = (0 && --b),=从右到左计算
0 && --b,&&从左到右评估短路
0, 评估 false 触发短路并取消下一步--b, 因短路未评估0a, 评估变量引用a = 0,分配发生,总体结果是 0你说
+and没有特定的顺序*,但是这个表显示的顺序是从左到右。为什么这样?
该表的最后一列是关联性。当我们两次使用相同的运算符或使用具有相同优先级的运算符时,结合性会打破优先级关系。
例如,我们应该如何阅读a / b / c. 是吗:
(a / b) / c, 或者a / (b / c)?根据该表/具有从左到右的结合性,所以它是第一个。
链式作业怎么样foo = bar = baz?现在,赋值具有从右到左的结合性,因此正确的解析是foo = (bar = baz)。
如果这一切都变得令人困惑,请关注一个简单的经验法则:
“优先级和关联性与评估顺序无关。”