如何计算 C 中运算符优先级 table 的表达式?
How to tally the expression with operator precedence table in C?
我知道下面的代码不是用 C 编写表达式的好方法,可能有很多 post 已经劝阻这样的 post,但我确信输出不是编译器依赖。
代码如下所示:
#include <stdio.h>
int main() {
int x = 2;
int y = 1;
int z = x || ++y;
printf("%d %d %d\n", x, y, z);
return 0;
}
我有以下问题:
现在我知道短路会发生并且 ++y
永远不会被评估但是如果我没记错的话,一元运算符的优先级高于逻辑运算符因此 ++y
应该先发生,表达式应该从反向短路,对吗?
还有一个问题是,如果短路从左侧开始发生,那么x
首先被评估,然后因为短路,x的值应该被分配给 z
,但得到的答案是 1。为什么这样?
关于 Cppreference 的 order of evaluation 文章在这里是一个有用的资源。
问题 1
运算符结合性和求值顺序之间存在差异。前者指定如何解析(子)表达式,或者换句话说“将括号放在哪里”。后者处理是否以及以什么顺序评估子表达式。
引用Cppreference上给出的例子:
[..] the expression f1() + f2() + f3()
is parsed as (f1() + f2()) + f3()
due to left-to-right associativity of operator+, but the function call to f3
may be evaluated first, last, or between f1()
or f2()
at run time.
关于评估顺序有几条规则。这里的一个重要概念是序列点:
If a sequence point is present between the subexpressions E1 and E2, then both value computation and side effects of E1 are sequenced-before every value computation and side effect of E2.
由于使用了逻辑或运算符,语句 int z = x || ++y;
包含一个序列点:
- There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators:
&&
(logical AND), ||
(logical OR), and ,
(comma).
结合两个引用,这意味着 x
将首先被评估。由于 x
不为零,因此不计算 OR 表达式的右侧,逻辑或运算符的结果为 1
(请参阅 here)。这也意味着 ++y
的副作用 不会 发生。
此行为是根据 C 标准定义的,因此 不 编译器相关(即未 实现定义 )。
问题 2
这里的逻辑或运算符 而不是 结果是 x
,因为它代表一个布尔值。在 C 中,对于所有布尔表达式,int
类型 1
表示真表达式,int
类型 0
表示假表达式。
输出
代码将为 x y z
打印 2 1 1
,因为 x
和 y
自初始化以来未更改,逻辑或运算符导致 1
.
我知道下面的代码不是用 C 编写表达式的好方法,可能有很多 post 已经劝阻这样的 post,但我确信输出不是编译器依赖。
代码如下所示:
#include <stdio.h>
int main() {
int x = 2;
int y = 1;
int z = x || ++y;
printf("%d %d %d\n", x, y, z);
return 0;
}
我有以下问题:
现在我知道短路会发生并且
++y
永远不会被评估但是如果我没记错的话,一元运算符的优先级高于逻辑运算符因此++y
应该先发生,表达式应该从反向短路,对吗?还有一个问题是,如果短路从左侧开始发生,那么
x
首先被评估,然后因为短路,x的值应该被分配给z
,但得到的答案是 1。为什么这样?
关于 Cppreference 的 order of evaluation 文章在这里是一个有用的资源。
问题 1
运算符结合性和求值顺序之间存在差异。前者指定如何解析(子)表达式,或者换句话说“将括号放在哪里”。后者处理是否以及以什么顺序评估子表达式。
引用Cppreference上给出的例子:
[..] the expression
f1() + f2() + f3()
is parsed as(f1() + f2()) + f3()
due to left-to-right associativity of operator+, but the function call tof3
may be evaluated first, last, or betweenf1()
orf2()
at run time.
关于评估顺序有几条规则。这里的一个重要概念是序列点:
If a sequence point is present between the subexpressions E1 and E2, then both value computation and side effects of E1 are sequenced-before every value computation and side effect of E2.
由于使用了逻辑或运算符,语句 int z = x || ++y;
包含一个序列点:
- There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators:
&&
(logical AND),||
(logical OR), and,
(comma).
结合两个引用,这意味着 x
将首先被评估。由于 x
不为零,因此不计算 OR 表达式的右侧,逻辑或运算符的结果为 1
(请参阅 here)。这也意味着 ++y
的副作用 不会 发生。
此行为是根据 C 标准定义的,因此 不 编译器相关(即未 实现定义 )。
问题 2
这里的逻辑或运算符 而不是 结果是 x
,因为它代表一个布尔值。在 C 中,对于所有布尔表达式,int
类型 1
表示真表达式,int
类型 0
表示假表达式。
输出
代码将为 x y z
打印 2 1 1
,因为 x
和 y
自初始化以来未更改,逻辑或运算符导致 1
.