提问人:Guest Man 提问时间:11/13/2023 最后编辑:Guest Man 更新时间:11/13/2023 访问量:102
这个表达的结果不是我学到的
result of this expression is not what i learned
问:
在下面的代码中,结果为 -6。为什么?
` int x = 5;
int y = 3;
int result = x++ - (--y + ++x) - y--;`
我认为首先,在括号内评估,然后在括号外按从左到右的顺序进行评估,但这样,结果就不会是-6。 在我看来,这是顺序:
- ++x
- --y
- X++的
- G-S
- 第一个 - 从左起
-
- 在表达过程中
- 最后 - 从左起
在数字 1 中,值为 6,x 为 6
在数字 2 中,值为 2,y 为 2
在数字 3 中,值为 6,x 为 7
在数字 4 中,值为 2,y 为 1
在数字 5,6,7 中,表达式为 6 - 8 - 2 = -4,不等于 -6;
在运算符优先级和运算符关联性方面
答:
1赞
PajLe
11/13/2023
#1
引用 C# 规范(ECMA-334,第 6 版,2022 年 6 月,§11.4.1):
表达式中的操作数按从左到右的顺序计算。
这意味着你最初的假设是不正确的:“我认为首先,括号内评估了”。
在这种情况下,将首先进行评估;序列如下所示:x++
x++
被计算,返回 5,但在 x 中保存 6--y
被计算,返回 2,并在 y 中保存 2++x
计算结果为 7(因为上一次操作为 6)x
- 括号中的内容被计算 (2 + 7) = 9
- 计算第一个减法:(从步骤 1 开始。 (从步骤 4 开始。=
5
-
9
-4
y--
得到评估,返回 2,但在 y 中保存 1- 最终减法得到计算:(从步骤 5 开始。 (从步骤 6 开始。=
-4
-
2
-6
正如其中一条评论(优先级、关联性与顺序)中提到的,区分以下因素很重要:
-
优先级规则描述当表达式混合使用不同类型的运算符时,应如何用括号括号括住带括号的表达式
-
关联性规则描述当表达式具有一堆相同类型的运算符时,应如何用括号括起来的表达式
-
计算规则的顺序描述表达式中每个操作数的计算顺序
评论
0赞
Guest Man
11/13/2023
感谢您的回复。那么什么是从左到右或从右到左的关联性?例如,我听说后增量/递减是从右到左,但递增/递减前是从左到右。此规则将在哪里适用?如果这是真的,++x 应该在 --y 之前计算。
0赞
PajLe
11/14/2023
从规范中可以看出: 当操作数发生在具有相同优先级的两个运算符之间时,运算符的关联性控制操作的执行顺序。 ++x 和 --y 都是一元运算。我们仍然可以谈论它们的关联性,但这可能会令人困惑。--x 和 ++x 保持关联,这意味着您将首先“评估”,然后 .x++ 的正确关联意味着您将首先“评估”,然后--
x
++
x
0赞
PajLe
11/14/2023
对于您给出的示例,no 是因为这两个操作数之间的运算符是 ,并且是左关联的(除了赋值运算符和 null 合并运算符外,所有二进制运算符都是左关联的,这意味着运算是从左到右执行的。If this is true , ++x should evaluate before --y
+
+
)
0赞
Jeremy Lakeman
11/13/2023
#2
int result = x++ - (--y + ++x) - y--;
生成的 IL 大致相当于;
var t0 = x;
var t1 = t0 + 1;
x = t1;
var t2 = y;
var t3 = t2 - 1;
y = t3;
var t4 = x;
var t5 = t4 + 1;
x = t5;
var t6 = t3 + t5;
var t7 = t0 - t6;
var t8 = y;
var t9 = t8 - 1;
y = t9;
var t10 = t7 - t8;
int result = t10;
您提供的值从左到右计算。当左手值和右手值都可用时,将计算二进制运算。括号强制将哪些值绑定到每个二进制操作的左手和右手。
评论
x++ - (--y + ++x) - y--
对于您输入的内容,并将评估为 .括号不优先考虑“以哪个顺序做++
或--
”,而是优先考虑“按哪个顺序计算结果”。所以顺序看起来像“首先通过++
/--
获取所有结果值,然后在括号中计算值,然后从左边的第一个值中减去它,然后减去右边的值”。而不是“在括号中获取结果值并计算它们,然后计算左值并从中减去括号部分的结果,然后计算右值并减去它”。x = 5
y = 3
5 - (2 + 7) - 2