【问题标题】:Post Increment Infinite loop i += i++; [duplicate]后增量无限循环 i += i++; [复制]
【发布时间】:2017-07-02 07:09:15
【问题描述】:

我不明白为什么这个后增量方程不增加。我原以为在 += 操作之后该值会增加 1,然后第二次 i 将有一个 1 值。但是输出是一个零零的无限循环。有谁能解释为什么“我”不增加。

int i = 0;
for(; ; ) {
  if ( i >= 10) break;
  i += i++;
}
System.out.println(i);

【问题讨论】:

  • 附带说明,行为来自如何定义后增量以及 += 运算符的工作方式。在 JS 中可以观察到相同的行为,并且可能在其他语言中也可以观察到。
  • Java Puzzlers 有一个类似但稍微复杂一点的谜题,名为 Inclement Increment
  • 在 Java 和 C# 中它输出无限循环。但在 C 中,它的输出类似于代码:i += ++i; Changes from language to language.
  • @HasanAlperOcalan - 我希望在 C 中它会触发未定义的行为。在这种情况下说“C 做 X”可能是错误的。

标签: java increment


【解决方案1】:

让我们检查一下i += i++;

i++ 表示读取i 的值,然后递增i

i += x 表示评估i,然后评估x 并加上2 并将结果放入i

那么,会发生什么:

  • i 被评估,它是 0
  • i++ 被评估。它返回0,并且i 的值设置为1
  • i += i++ 现在是 i = 0 + 0
  • i = 0

尝试使用++i 在读取其值之前获取增量结果。

【讨论】:

    【解决方案2】:

    毫无疑问你会进入无限循环..

    class Demo{
      public static void main(String[] args){
        int i = 0;
        for( ; ; ) {
            if (i >= 10) 
                break;
            i = i+i++;
            System.out.println(i);
        }
      }
    }
    

    假设上面的代码,我刚刚用编译器将替换的增量替换了你的行。

    现在,最初 i=0; 所以

    i = i+i++
    

    结果 i = 0 + 0 // 现在 i 是 1

    但最后你又让 i 等于 0!

    因此无穷大...

    【讨论】:

      【解决方案3】:

      虽然@njzk2 的答案是正确的,但指出为什么它是正确的很有用。

      还有其他的可能——例如,为什么Java在赋值后不执行后自增运算符? (答案:因为那不是 Java 语言设计者选择的)

      复合赋值(如+=)的评估顺序在 Java 语言规范第 15.26.2 节中指定。我会引用how it is defined for Java 8:

      • 首先,计算左侧操作数以生成变量。如果此评估突然完成,则赋值表达式 出于同样的原因突然完成;右手操作数不是 评估,没有分配发生。

      • 否则,将保存左侧操作数的值,然后计算右侧操作数。如果此评估完成 突然,然后赋值表达式突然完成 同样的原因,没有分配发生。

      • 否则,使用左侧变量的保存值和右侧操作数的值进行二元运算 由复合赋值运算符指示。如果这个操作 突然完成,然后赋值表达式突然完成 出于同样的原因,没有分配发生。

      • 否则二元运算的结果转换为左侧变量的类型,进行值集转换 (§5.1.13)到适当的标准值集(不是 扩展指数值集),转换的结果是 存储到变量中。

      最重要的是先保存左手表达式的值,再把右手完全求值,再把复合运算的结果存入左边的变量中。

      【讨论】:

      • 正确,但毫无意义。这是 UB 完全合理的情况之一。
      • @KevinZ 您可能指的是 C 中的未定义行为 (UB)。谈到 Java,我不同意您的说法。 Java 的理念是使其尽可能跨平台。 Java 中没有完全未定义的行为,尽管在规范范围内,平台之间的某些行为可能会有所不同。 C/C++ 的设计理念不同。
      猜你喜欢
      • 2017-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 2011-05-14
      • 2011-10-06
      • 2013-04-26
      • 2018-06-25
      相关资源
      最近更新 更多