正确理解i=i++ i+=i++ i=i++ + i++

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正确理解i=i++ i+=i++ i=i++ + i++相关的知识,希望对你有一定的参考价值。

最近笔试经常能够碰到i=i++的问题,这个问题还是比较简单,不过手贱的自己偏偏想去看看i+=i++,不看不要紧,一看看出了大问题

几个常识

1.result+=expression在所有语言当中都是等价于result=result+expression

2.int i=b++;这个操作是如何完成的呢,首先系统将内存栈中b的值拷贝到寄存器当中,然后将该拷贝值+1 将结果写到a中

步入正题

以下会论述C语言和java语言的执行情况

首先看看这段代码,大家觉得i的值是多少

int i=0;
i=i++;

  C:1  java:1

再看看这段代码,大家又觉得i的值是多少呢

int i=0;
i+=i++;

 C:1  java:0

最后看看这个

int i=0;
i+=i++ + i++ 

C:3  java:1

大家现在是什么感觉,反正我一开始是懵逼的,为什么会出现这种情况呢,下面慢慢解释

 

 先看第一种情况

 i=i++实际上是从先从栈中拷贝i的值到寄存器当中,然后将执行加法运算,返回进行加法运算前的值,所以结果是0,实际上等价于如下函数:

int mockAdd(int &i){
 int temp=i;
 i=i+1;
 return temp;
}

这在C语言和java当中都是统一的,相信大家也很好理解

 

再看看第二种情况

i+=i++可以理解为i=i+i++这在两个语言当中也是统一的,但是为什么C语言是等于1,java是等于0呢

C语言的比较好理解:

这个运算首先执行i++ 此时i的值为1 该运算返回0 于是计算表达式变为i=i+0

然后计算i=1+0 结果为1

java语言的怎么理解呢,我们看看java的字节码文件

public class Test1{
  public static  void main(String[]args){
    int i=0;
    i+=i++;
  }
}
对应字节码核心文件
public static void main(java.lang.String[]);
    Code:
       0: iconst_0 //定义了一个常量0
       1: istore_1 //将0存到变量1中,这儿的变量就是我们的i
       2: iload_1  //将i的值读取到寄存器当中
       3: iload_1 //将i的值读取到寄存器当中
       4: iinc          1, 1 //执行++运算
       7: iadd //执行加法运算
       8: istore_1 //将运算结果存到变量1中
       9: return //返回
}

 答案很明显 当i=0时 java进行i=i+i+=这个过程时,先把左右两端i的值都取出来再运算,于是实际上的运算就是i=0+0++ 答案可不是就是0吗

 

再看看第三种情况

i+=i++ + i++ 等价于i=i+ i++ + i++ 根据从左到右和优先级关系 可以得出如下执行过程

先执行i=i+ 0++ +i++,执行完之后i=1,表达式变为i=i+0+i++

然后执行i=i+1+1++ ,执行完之后i=2 表达式变为i=i+1

最后一步就是执行i=2+1了结果为3,

java语言怎么理解呢,还是字节码说话,如下:

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

//核心字节码如下
 public static void main(java.lang.String[]);
    Code:
       0: iconst_0 //定义一个常量0
       1: istore_1 //将0存储到变量1中 也就是我们的i
       2: iload_1  //读取i的值到寄存器
       3: iload_1 //读取i的值到寄存器
       4: iinc          1, 1 //执行自增操作
       7: iload_1 //读取i的值到寄存器
       8: iinc          1, 1 //执行自增操作
      11: iadd //进行加法运算
      12: iadd //进行加法运算
      13: istore_1 //将运算协会变量i
      14: return //返回
}

 通过字节码我们可以看出在i=0时,i=i+ i++ i++ 实际上是先执行 i=0+0++ +i++ 最后i=1++ 答案也就是0

最终的总结

1.C语言的算术表达式运算指令的优先级高于值拷贝的优先级

   java语言的算术表达式运算指令低于值拷贝的优先级

2.具个例子

   int i=a+b++,C语言会先取b的值拷贝到寄存器,执行++运算后才会再去取b的值

   int i=a+b++,C语言会先拷贝a的值到寄存器,再拷贝b的值到寄存器,执行完++运算再去之前的拷贝值相加

 

  

 

以上是关于正确理解i=i++ i+=i++ i=i++ + i++的主要内容,如果未能解决你的问题,请参考以下文章

i++与++i的理解

Java中的I/O流

理解i++和++i

关于i++,++i 的理解

Flink 原理——异步I/O(asynchronous I/O)

查找 i*i+1 是不是为素数,汇编语言