C 与 Java 中的表达式计算

l s*_*thi 0 c java variables expression operators

int y=3;
int z=(--y) + (y=10);
Run Code Online (Sandbox Code Playgroud)

当在 C 语言中执行时, 的值z计算为 20,但当在 java 中执行相同的表达式时,执行时的z值为 12。

谁能解释为什么会发生这种情况以及有什么区别?

klu*_*utt 6

在 C 语言中执行时,z 的值为 20

不,不是的。这是未定义的行为,因此z可以获得任何值。包括20。程序理论上也可以做任何事情,因为标准没有说明程序遇到未定义行为时应该做什么。在此处阅读更多信息:未定义、未指定和实现定义的行为

根据经验,不要在同一个表达式中两次修改变量。

这不是一个好的副本,但这会更深入地解释事情。此处未定义行为的原因是序列点。 为什么这些构造使用前后增量未定义行为?

在 C 中,当涉及算术运算符时,例如+and /,标准中未指定操作数的求值顺序,因此如果对这些求值有副作用,您的程序将变得不可预测。下面是一个例子:

int foo(void)
{
    printf("foo()\n");
    return 0;
}

int bar(void)
{
    printf("bar()\n");
    return 0;
}

int main(void)
{
    int x = foo() + bar();
}
Run Code Online (Sandbox Code Playgroud)

这个程序会打印什么?好吧,我们不知道。我不完全确定这个片段是否会调用未定义的行为,但无论如何,输出是不可预测的。我提出了一个问题,以未指定的顺序使用具有副作用的函数是否是未定义的行为?,关于那个,所以我稍后会更新这个答案。

其他一些变量具有指定的评估顺序(从左到右),例如||and&&和 此功能用于短路。例如,如果我们使用上面的示例函数并使用foo() && bar(),则只会foo()执行该函数。

我对Java不是很精通,但为了完整性,我想提一下,除了非常特殊的情况,Java基本上没有未定义或未指定的行为。Java 中的几乎所有内容都定义良好。有关更多详细信息,请阅读rzwitserloot 的回答