我不明白{int a=10; a+=++a-5/3+6*a;System.out.print(a);}输出 86

I do not understand how {int a=10; a+=++a-5/3+6*a; System.out.print(a);} outputs 86

提问人:Vyagh 提问时间:11/5/2023 最后编辑:user207421Vyagh 更新时间:11/5/2023 访问量:61

问:

我不明白怎么回事

{
    int a = 10;
    a += ++a-5/3+6*a;
    System.out.print(a);
}

输出 86

我知道速记符号的优先级低于此处使用的任何运算符,因此我的思维过程是将其视为

a = a + ++a-5/3+6*a

因此,如果我应用优先级将值增加到 11,然后和 ,那么为什么不将此表达式 (76) 的结果添加到 11(递增值)?++aa5/3=16*11=66a

现在我所理解的是,表达式的净值是 76 与旧值 10 相加。我不明白为什么,因为当我们计算表达式时,我们确实增加了 a 值,但是我现在如何使用旧值?++a-5/3+6*aa

java 表达式-求值 前缀-运算符

评论

3赞 user2357112 11/5/2023
优先级控制参数分组,而不是计算顺序。
0赞 Vyagh 11/5/2023
请你给我解释一下,我最近开始学习JAVA,所以我不明白你的意思。
0赞 user207421 11/5/2023
可以把它想象成 ,从左到右计算。因此,RHS上的第一个仍然具有其原始价值。a = a+(++a)-5/3+6*aa
0赞 user85421 11/5/2023
Vyagh,Java 语言规范 15.26.2。复合赋值运算符解释了如何计算:“首先,对左侧操作数进行计算......保存左侧操作数的值,然后计算右侧操作数...左边变量的保存值和右边操作数的值用于执行二进制操作“(我建议永远不要写这样的代码)+=
0赞 user85421 11/5/2023
(顺便说一句,这个问题本可以简化为更清楚一点,至少我解释这是这里的问题;顺便说一句2 标题不是真正的标题:)a += ++a+=

答:

-1赞 sram21 11/5/2023 #1

表达式 int a=10;a+=++a-5/3+6*a;System.out.print(a);是算术运算和赋值的组合。 让我们一步一步地分解它,以了解它为什么输出 86:

int a=10;:这会将变量 a 初始化为值 10。

++a:这是一个预增量操作,因此它将 a 的值递增 1,a 变为 11。

5/3:这是一个整数除法,结果为 1(因为它删除了小数部分)。

6*a:将 a 的当前值(即 11)乘以 6,得到 66。

现在,将上述操作放在一起:

++a 导致 a 为 11。 5/3 结果为 1。 6a 结果为 66。 因此,表达式 ++a-5/3+6a 的计算结果为 11 - 1 + 66,等于 76。

现在,让我们回到原来的任务:

A 当前值为 10。 a += 76 等同于 a = a + 76,它将 a 的值更新为 86。 最后,System.out.print(a) 打印 a 的值,即 86。

评论

1赞 user2357112 11/5/2023
“A 当前的值为 10” - 它以值 10 开头,但在计算后具有值 11。核心问题是为什么这里使用值 10 而不是 11。++a
0赞 sram21 11/5/2023
代码 int a=10;a+=++a-5/3+6*a;在 Java 中没有明确定义,因为它试图在同一步骤中更改和使用 a 的值,从而导致不可预测的结果。在这里,a 以 10 开头。但是,当我们执行 ++a 时,它会将 a 更改为 11。但紧接着,它就使用了 10 个,这令人困惑。这种行为在 Java 中并不可靠,为了清晰和一致,最好避免编写此类代码。最好遵循以下代码 int a = 10;一个++;将 a 递增 1 a = a - 5/3 + 6*a;使用递增值 System.out.print(a);
5赞 Stephen C 11/5/2023
@sram21 - 实际上,Java 中的行为是 100% 完全定义的。JLS确切地说明了发生了什么。没有未指定或不可预测的结果......假设变量不与其他线程共享。(对于对规范没有深入了解的人来说,结果可能会出乎意料,但那是另一回事。这种晦涩难懂的/代码永远不应该写在真正的程序中......所以普通的程序员不应该遇到它。
2赞 Stephen C 11/5/2023
现在在 C(我认为是 C++)中,像上面这样的表达式确实有未指定的结果......但这在很大程度上是语言历史的结果。从理论上讲,他们本可以解决这个问题,但代价是迫使许多遗留代码在较新的编译器中表现得不同。潜在的中断会太高。Java 从第一天起就严格指定了每个操作的每个步骤的评估顺序,从而避免了这个问题。
0赞 user207421 11/5/2023
不回答被问到的问题。