Java 编译器如何评估数学表达式?

Java 编译器如何评估数学表达式?,java,c,compiler-construction,Java,C,Compiler Construction,我正在读一个问题,然后我做了以下几点 a = b + (c - (b = c)) + (a - (c = a)) 我用C和Java试过了。它适用于java,但不适用于C 当然,这取决于编译器如何计算这些表达式,在谷歌搜索之后,我没有找到答案。它在C中不起作用的原因是C没有明确指定C=a将在何时发生。它可以发生在该语句中引用它的另外两次之前或之后 因此,根据编译器决定何时执行赋值c=a,表达式的值会有所不同。它没有定义 i、 e.如果在c=a之前计算b=c,则b将取c的原始值。如果在之后求值,则

我正在读一个问题,然后我做了以下几点

a = b + (c - (b = c)) + (a - (c = a))
我用C和Java试过了。它适用于java,但不适用于C


当然,这取决于编译器如何计算这些表达式,在谷歌搜索之后,我没有找到答案。

它在C中不起作用的原因是C没有明确指定
C=a
将在何时发生。它可以发生在该语句中引用它的另外两次之前或之后

因此,根据编译器决定何时执行赋值
c=a
,表达式的值会有所不同。它没有定义


i、 e.如果在
c=a
之前计算
b=c
,则
b
将取
c
的原始值。如果在之后求值,则取
a

的值。您可以参考java以获得完美的答案。

编译器不会求值这些表达式(如果它们是常量,则可能会求值,但决不能有任何区别)。它只生成另一种语言中大致相同的代码(在
javac
情况下为JVM字节码,在
gcc
情况下为处理器生成机器码,
cl.exe
等等)。更糟糕的是,由于没有定义,任何事情都可能发生。例如,阅读一些既不是旧价值也不是新价值的东西。(对于32位机器上的64位值来说,这是可以理解的,因为写入新值需要两条指令)关于32位机器上的64位值,这是一个很好的观点。我从来没想过。(当然,我更喜欢首先避免未定义的行为,而不是试图推断出会发生什么。)@Mystical,我同意避免UB,但我发现如果我理解一个实现为什么会表现得异常,那么更容易记住它是UB,而不是简单地不指定。这只能指定它在Java中的工作方式。它无法解释为什么它在C中的工作方式不同。