运算符优先级和评估顺序
Operator precedence and evaluation order
我无法理解这个程序的输出:
#include<iostream>
using namespace std;
int main()
{
int x = 1 , y = 1, z = 1;
cout << ( ++x || ++y && ++z ) << endl; //outputs 1;
cout << x << " " << y << " " << z ; //x = 2 , y = 1 , z = 1;
return 0;
}
输出:
1
2 1 1
如果先计算 ||
那么这个输出是好的,但是 this 文章说 &&
比 ||
有更高的优先级,因此它必须是先评价。如果是这种情况,那么根据我的输出应该是:
1
1 2 2
as ++y && ++z
将计算为 true
,因此 ++x
不会被计算。
让我们将多余的括号放入:
( ++x || (++y && ++z ))
那么很容易看出,如果 ++x
为 0,(++y && ++z )
将 仅被计算 。所以你可以看到,无论运算符优先级如何, ||
的短路性质意味着仅当左侧为 0 时才评估右侧。
(如果计算右侧,请注意如果 ++y
不为 0,则 ++z
将 仅计算 。)
这个表达式
++x || ++y && ++z
等同于表达式
++x || ( ++y && ++z )
而不是这样
( ++x || ++y ) && ++z
如果逻辑 OR 表达式的第一个操作数被评估为真(如您的示例所示),则第二个操作数 ( ++y && ++z )
不会被评估。
&&
has a higher precedence than ||
, and thus it must be evaluated first.
没有。 Operator precedence 仅确定在解析表达式时运算符将如何更紧密地绑定到其参数(就像通过括号一样),它不会影响评估顺序。在这种情况下,它只是意味着 ++x || ++y && ++z
将被解析为 (++x) || (++y && ++z)
,而不是 (++x || ++y) && (++z)
.
注意operator||
的结合性是从左到右的,所以++x
会先计算,(++y && ++z)
因为短路不会计算评估(除了重载 operator||
)。
( ++x || (++y && ++z )) - 可以看作布尔值 - 只有 ++x 被评估。它的int值为2,boolean值为1(真)。
"Precedence" 影响分组,而不是顺序,这意味着如果关于哪个运算符是操作数 "belongs to" 可能存在任何歧义,则具有更高优先级的运算符首先得到它。
由于涉及两个二元运算符,因此可以通过两种方式读取表达式。
作为树,这些将是:
and
/\
or ++z [(++x || ++y) && ++z]
/ \
++x ++y
or
/\
++x and [++x || (++y && ++z)]
/ \
++y ++z
优先规则决定在 C++ 中选择后一棵树,因为中间操作数 ++y
与 &&
分组,而不是 ||
.
这些运算符的 "short-circuiting" 意味着评估必须从最左边的叶子开始(每个运算符必须首先评估其左腿,然后在需要时评估其右腿)。
因此,首先评估 ++x
,如果 ++x
为零,则 ||
仅继续其右腿,而事实并非如此。
(从图的精彩和艺术可以看出,不管&&
和||
的相对优先级如何,必须先计算++x
。)
我无法理解这个程序的输出:
#include<iostream>
using namespace std;
int main()
{
int x = 1 , y = 1, z = 1;
cout << ( ++x || ++y && ++z ) << endl; //outputs 1;
cout << x << " " << y << " " << z ; //x = 2 , y = 1 , z = 1;
return 0;
}
输出:
1
2 1 1
如果先计算 ||
那么这个输出是好的,但是 this 文章说 &&
比 ||
有更高的优先级,因此它必须是先评价。如果是这种情况,那么根据我的输出应该是:
1
1 2 2
as ++y && ++z
将计算为 true
,因此 ++x
不会被计算。
让我们将多余的括号放入:
( ++x || (++y && ++z ))
那么很容易看出,如果 ++x
为 0,(++y && ++z )
将 仅被计算 。所以你可以看到,无论运算符优先级如何, ||
的短路性质意味着仅当左侧为 0 时才评估右侧。
(如果计算右侧,请注意如果 ++y
不为 0,则 ++z
将 仅计算 。)
这个表达式
++x || ++y && ++z
等同于表达式
++x || ( ++y && ++z )
而不是这样
( ++x || ++y ) && ++z
如果逻辑 OR 表达式的第一个操作数被评估为真(如您的示例所示),则第二个操作数 ( ++y && ++z )
不会被评估。
&&
has a higher precedence than||
, and thus it must be evaluated first.
没有。 Operator precedence 仅确定在解析表达式时运算符将如何更紧密地绑定到其参数(就像通过括号一样),它不会影响评估顺序。在这种情况下,它只是意味着 ++x || ++y && ++z
将被解析为 (++x) || (++y && ++z)
,而不是 (++x || ++y) && (++z)
.
注意operator||
的结合性是从左到右的,所以++x
会先计算,(++y && ++z)
因为短路不会计算评估(除了重载 operator||
)。
( ++x || (++y && ++z )) - 可以看作布尔值 - 只有 ++x 被评估。它的int值为2,boolean值为1(真)。
"Precedence" 影响分组,而不是顺序,这意味着如果关于哪个运算符是操作数 "belongs to" 可能存在任何歧义,则具有更高优先级的运算符首先得到它。
由于涉及两个二元运算符,因此可以通过两种方式读取表达式。
作为树,这些将是:
and
/\
or ++z [(++x || ++y) && ++z]
/ \
++x ++y
or
/\
++x and [++x || (++y && ++z)]
/ \
++y ++z
优先规则决定在 C++ 中选择后一棵树,因为中间操作数 ++y
与 &&
分组,而不是 ||
.
这些运算符的 "short-circuiting" 意味着评估必须从最左边的叶子开始(每个运算符必须首先评估其左腿,然后在需要时评估其右腿)。
因此,首先评估 ++x
,如果 ++x
为零,则 ||
仅继续其右腿,而事实并非如此。
(从图的精彩和艺术可以看出,不管&&
和||
的相对优先级如何,必须先计算++x
。)