【问题标题】:a += a++ * a++ * a++ in Java. How does it get evaluated?Java 中的 a += a++ * a++ * a++。它是如何被评估的?
【发布时间】:2012-11-02 09:25:12
【问题描述】:

我遇到了这个问题in this website,并在 Eclipse 中尝试过,但无法理解它们是如何被评估的。

    int x = 3, y = 7, z = 4;

    x += x++ * x++ * x++;  // gives x = 63
    System.out.println(x);

    y = y * y++;
    System.out.println(y); // gives y = 49

    z = z++ + z;
    System.out.println(z);  // gives z = 9

根据网站上的评论,x += x++ * x++ * x++ 解析为 x = x+((x+2)*(x+1)*x),事实证明这是真的。我想我错过了关于这个运算符优先级的一些东西。

【问题讨论】:

  • x += 3 * 4 * 5; = 3 + 60 = 63; y = 7 * 7 = 49, z = 4 + 5 = 9
  • 为什么这个问题被选为 C++ 问题的副本?
  • (我同意 NullUserException - C/C++ 有不同 规则来处理相同的结构,但它恰好在 Java 下定义良好,如果不是丑陋的话。 )

标签: java operator-precedence post-increment


【解决方案1】:

Java 根据表达式的优先级从左到右 & 评估表达式。

int x = 3, y = 7, z = 4;

x (3) += x++ (3) * x++ (4) * x++ (5);  // gives x = 63
System.out.println(x);

y = y (7) * y++ (7);
System.out.println(y); // gives y = 49

z = z++ (4) + z (5);
System.out.println(z);  // gives z = 9

后缀增量运算符仅在使用/返回变量后递增变量。一切似乎都是正确的。

这是后缀自增运算符的伪代码:

int x = 5;
int temp = x;
x += 1;
return temp;

来自 JLS 15.14.2 (reference):

后缀自增表达式的值是新值存储前变量的值。

【讨论】:

  • 感谢您最后的陈述 :) 让我们更容易理解 ++x 是如何计算的。在这个例子之前总是对 ++x 感到困惑。
  • 'Java 根据表达式的优先级从左到右评估表达式'在术语上是矛盾的。 Java 从左到右计算操作数运算符按照运算符优先级和关联性规定的顺序进行评估。
【解决方案2】:

因为后增量会在取值后修改变量,而 += 在评估其右侧之前先评估其左侧,

x += x++ * x++ * x++; 

变成

tmp0 = x

tmp1 = x
++x
tmp2 = tmp1 * x
++x
tmp3 = tmp2 * x
++x

x = tmp0 + x

【讨论】:

  • 你确定你的意思是在右手边之前评估左侧,因为我想我知道相反的情况吗?代码分解很好,除了最后一条语句 x = tmp0 + x 不会导致 x = 3 为 63。
  • 否则将是 66 而不是 63。
【解决方案3】:

后缀运算符x++ 的意思是“现在给我 x 的值,但增加它以供将来参考”

所以,通过order of operations and evaluation

x++ * x++ * x++

首先被解释为

3 * 4 * 5 (=60)

然后将其添加到 原始 3,得到 63。

使用原始值因为它在同一行,你是否写过类似的东西:

int x = 3;

int y += x++ * x++ * x++; 
x += y;

x 现在是 66,而不是 63,因为第二行中的 x 现在是 6,而不是原来的 3。

【讨论】:

    【解决方案4】:

    一元运算符从左到右求值,所以第一个x++ 得到值x,第二个是(x+1),等等。+= 在开始时根据x 的值求值,因此添加x

    【讨论】:

      【解决方案5】:

      与运算符优先级本身无关,只是评估顺序。 这里有两件事要知道:

      1. x++ 是后缀增量,因此x 的值在评估后递增
      2. * 评估右侧然后评估左侧。

      考虑到第 2 点,表达式x++ * x++ * x++ 可以更具体地重写为x++ * (x++ * (x++))

      整个表达式可以写成过程:

      a = x
      x += 1
      b = x
      x += 1
      c = a*b
      d = x
      x += 1
      return c*d
      

      【讨论】:

      • +1,但使用 nitpick:实际上,运算符优先级在任何地方都有效,表达式或语句中有多个运算符:) 前缀和后缀运算符的优先级高于二元运算符,并且这就是为什么x++ * x++ 可以写成不带括号。你必须写(x++) * (x++)。如果没有运算符优先级和括号,只会发生从右到左,它可能表示x ++ * (x++)),例如可能是语法错误:*没有LHS操作数
      • 好的,很公平。我的意思是,答案更多地与后缀和前缀运算符的行为有关,而不是运算符优先级,就像混合了许多不同优先级的运算符的表达式一样(例如x++ * x++ + x++ / x++
      【解决方案6】:

      因为在变量 x 之后添加了自增运算 ++。这是一个后增量操作。这意味着,x 在处理操作后递增。

      In your example the expression would be: 
      x += 3 * 4 * 5
      First the expression is added by 3 (x+=....)
      then the first x++ results in 3
      the second x++ results in 4 (because it was incremented before)
      and the third x++ results in 5.
      

      如果你想让你的变量在操作执行之前递增,你必须写++x(预递增操作)

      【讨论】:

        猜你喜欢
        • 2019-12-28
        • 2018-07-01
        • 2023-04-04
        • 1970-01-01
        • 2012-02-20
        • 1970-01-01
        • 2019-05-31
        • 2017-11-21
        • 1970-01-01
        相关资源
        最近更新 更多