当前位置: 首页 > 面试题库 >

为什么此表达式i + = i ++与Java和C不同?

鲜于承基
2023-03-14
问题内容

我知道前缀和posfix操作… i和i 之间的区别等等。

但是我想我在这里想不到的东西。在下面可以找到代码:

package test;

public class Test
{
    public static void main (String[] args)
    {
        int i=0;

        i+=i++;
        System.out.println(i); // Prints 0

        i = i + (i++);
        System.out.println(i); // Prints 0

        i = i + (i+1);
        System.out.println(i); // Prints 1

    }
}

因此输出为:

0
0
1

我在C中尝试了相同的代码:

#include <stdio.h>
#include <string.h>

main()
{
    int i=0;

    i+=i++;

    printf("%d", i);   // prints 1

    i = i + (i++);
    printf("%d", i);   // prints 3

    i = i + (i+1);
    printf("%d", i);   // prints 7
}

输出为:

1
3
7

为什么在C中相同的代码增加值时i+=i++却不增加i


问题答案:

爪哇

在Java中,表达式具有明确定义的含义。复合赋值运算符的规范说:

形式为 E1 op = E2 的复合赋值表达式等效于 E1 =(T)((E1)op(E2)) ,其中 TE1 的类型,只是
E1 仅被评估一次。

在运行时,可以通过以下两种方式之一对表达式求值。如果左侧操作数表达式不是数组访问表达式,则需要四个步骤:

  • 首先,对左操作数求值以产生一个变量。如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,并且不会发生赋值。
  • 否则,将保存左侧操作数的值,然后评估右侧操作数。如果该评估突然完成,则赋值表达式由于相同的原因突然完成,并且不会发生赋值。
    * 否则,将使用左手变量的保存值和右手操作数的值执行复合赋值运算符指示的二进制运算。如果该操作突然完成,则赋值表达式由于相同的原因而突然完成,并且不会发生赋值。
    * 否则,将二进制运算的结果转换为左侧变量的类型,并进行值集转换(第5.1.13节)为适当的标准值集(而不是扩展指数值集),然后将结果转换的结果存储到变量中。


所以

i += i++;

相当于

i = i + i++;

因为左侧的值在开始时被保存,然后又添加到右侧的值,并且由于Java中的表达式求值是从左到右的,所以对iby i++的修改被后续赋值覆盖。

这一切都意味着

i += i++;

相当于

i += i;

C

在C表达式

i += i++;

具有未定义的行为。因此,执行此代码时可能会发生任何事情。这意味着您无法预测i语句完成后的值。

因此,完全可以预期C程序的输出与Java程序的输出不同。



 类似资料:
  • 是 i = 表达式;等于i =表达式,那么登录的目的是什么? 大家好,我对下面这个问题很困惑;i =表达式;//意味着i = i表达式那么这个i =表达式呢;//我在eclipse上进行了测试,简单地找到了结果i = expression 所以 i = 表达式;等于 i = 表达式 那么登录的目的是什么? 我知道黑白 i(前增量)和 i(后增量)的区别 谢谢你!

  • 问题内容: 以下Java程序平均需要0.50秒至0.55秒的时间运行: 如果我替换为,则需要0.60到0.65秒的时间来运行。怎么会? 我对该程序的每个版本运行了15次,两次交替运行。结果如下: 最快的运行时间比最慢的运行时间长。如果它们具有相同的效率,则发生这种情况的可能性将小于。 问题答案: 字节码的顺序略有不同。 : vs : 乍看之下,这没有什么区别;如果有的话,第二个版本更理想,因为它减

  • 问题内容: 有人告诉我,+=效果可能与的标准符号不同i = i +。是否有与以下情况i += 1不同的情况i = i + 1? 问题答案: 这完全取决于对象i。 +=调用__iadd__方法(如果存在- 如果不存在则返回),而+调用方法1或在某些情况下调用方法2。 从API的角度来看,应该将其用于就地修改可变对象(返回已变异的对象),而__add__应该返回某些东西的新实例。对于不可变的对象,这两

  • 问题内容: 哪个更正确?Java的结果为12或C =13。或者,如果不是正确性,请详细说明。 问题答案: 没有比这更正确的了。它实际上是未定义的,称为序列点错误。 http://en.wikipedia.org/wiki/Sequence_point

  • 问题内容: 当我尝试在/ decrement中写一个后缀/前缀,然后在/ decrement中写一个后缀/前缀时,出现以下错误: 操作++ /-的无效参数 。 但是,根据JLS: 和 所以写: 应该有可能…有什么想法吗? 问题答案: 请注意,原始语法缺少任何语义。这只是语法,并不是每个语法上有效的程序通常都是有效的。例如,语法通常没有涵盖使用前必须声明变量的要求(可以,但是很麻烦)。 Postfi

  • 本文向大家介绍为什么“ while(i ++ 相关面试题,主要包含被问及为什么“ while(i ++ 时的应答技巧和注意事项,需要的朋友参考一下 正如其他人指出的那样,该测试在许多方面都有缺陷。 你没有告诉我们到底 如何 ,你做了这个测试。但是,我试图实施这样的“幼稚”测试(无冒犯): 当使用默认设置运行它时,似乎有很小的差异。但是,当您使用该标志运行基准测试时,基准测试的 真正 缺陷就变得显而