首页 > 其他分享 >i++和++i的爱恨情仇

i++和++i的爱恨情仇

时间:2024-02-18 11:35:43浏览次数:24  
标签:++ 情仇 L1 IINC LINENUMBER 爱恨 ISTORE ILOAD

起因是一个群友提出的问题,问以下Java代码的输出的结果是什么?

        int i = 1;
        int j = ((++i) + (++i));
        System.out.println(j);

众所周知,单个的++i赋值是先计算+1然后计算,单个的i++服之是先赋值后+1计算,但,多个操作复合起来就少有人知了。

接下来我们来研究一下。

经过测试,易得,结果是5。那么这个结果是怎么得到的呢?

首先我们将这段代码反编译一下,可得字节码如下:

  // access flags 0x9
  public static main([Ljava/lang/String;)V
    // parameter  args
   L0
    LINENUMBER 5 L0
    ICONST_1
    ISTORE 1
   L1
    LINENUMBER 6 L1
    IINC 1 1
    ILOAD 1
    IINC 1 1
    ILOAD 1
    IADD
    ISTORE 2
   L2
    LINENUMBER 7 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L3
    LINENUMBER 12 L3
    RETURN
   L4
    LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
    LOCALVARIABLE i I L1 L4 1
    LOCALVARIABLE j I L2 L4 2
    MAXSTACK = 2
    MAXLOCALS = 3

先看这一段字节码:

   L0
    LINENUMBER 5 L0
    ICONST_1
    ISTORE 1

可以知道,变量i的指针是1,初始值为1

ICONST 是指使用了int的几个常量(<=5)的指针,同理还有LCONST对应long,DCONST对应double。

注意:这里的_1中的1,是指针,指向了常量。

注意:非常量数值的数据压入操作会有所不同。

ISTORE 是将操作数栈顶上的int数值赋予本地变量,同理还有LSTORE,DSTORE等。

注意:ISTORE参数为指针

再来看来看这一段字节码:

   L1
    LINENUMBER 6 L1
    IINC 1 1
    ILOAD 1
    IINC 1 1
    ILOAD 1
    IADD
    ISTORE 2

首先将变量进行了IINC操作,给变量+1,其次使用ILOAD操作读取变量数值(当前为2),加入到操作数栈中。然后下面重复这个操作(当前为3)。最后调用了IADD进行了加法操作,将操作数栈中的两个数值2+3的结果赋予变量2(就是代码中的j变量)。

最后输出结果5。

IINC不影响操作数栈,但是会改对应变量的值,所以不需要重新使用ISTORE压入。

同理我们再来测试i++,代码如下:

        int i = 1;
        int k = ((i++) + (i++) + (i++));
        System.out.println(k);

字节码如下:

 // access flags 0x9
  public static main([Ljava/lang/String;)V
    // parameter  args
   L0
    LINENUMBER 9 L0
    ICONST_1
    ISTORE 1
   L1
    LINENUMBER 10 L1
    ILOAD 1
    IINC 1 1
    ILOAD 1
    IINC 1 1
    IADD
    ILOAD 1
    IINC 1 1
    IADD
    ISTORE 2
   L2
    LINENUMBER 11 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L3
    LINENUMBER 12 L3
    RETURN
   L4
    LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
    LOCALVARIABLE i I L1 L4 1
    LOCALVARIABLE k I L2 L4 2
    MAXSTACK = 2
    MAXLOCALS = 3

注意这一段字节码:

   L1
    LINENUMBER 10 L1
    ILOAD 1
    IINC 1 1
    ILOAD 1
    IINC 1 1
    IADD
    ILOAD 1
    IINC 1 1
    IADD
    ISTORE 2

可以看到,这里是先使用ILOAD操作读取数据到操作数栈中,然后再使用IINC进行自增,这里就体现了i++++i的区别。

至此,我们已经彻底了解了i++++i

但是,强烈不推荐这种写法,这种代码难以理解和维护。

参考文档

[1] javase11 jvm doc

标签:++,情仇,L1,IINC,LINENUMBER,爱恨,ISTORE,ILOAD
From: https://www.cnblogs.com/bloodcolding/p/18018983

相关文章

  • C++——数据类型笔记
    在C++编程中,了解各类数据类型也是至关重要的。下面我会总结一下C++中的数据类型,包括基本类型,符合类型和自定义类型。方便自己整理和理解。1,基本类型C++中的基本类型是构建其他数据类型的基础,常见的基础类型包括整型,浮点型,字符型和布尔型:整型:用于表示整数,如int、short......
  • 《安富莱嵌入式周报》第332期:铷时钟控制板,航天战斗机C++代码标准,免费开源芯片设计,在线
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 视频版https://www.bilibili.com/video/BV1tU421d7ZK/目录:1、Rubidium铷时钟控制板2、开源小设计,简易万用表连通性测试仪3、免费开源芯片设计软件Electric4、在线电路仿......
  • C++左值引用、右值引用、移动语义、完美转发、深浅拷贝
    一、左值和右值定义(能否取地址)1.左值:可以取地址的对象2.右值:不可以取地址、临时要销毁的对象二、左值引用1.定义:对左值的引用int&ra=a;2.作用:传递参数和返回值时减少不必要的拷贝三、右值引用1.定义:对右值的引用//以下是对几种右值的右值引用int&&rr1=10;doubl......
  • C++ 20 协程
    目录c++协程类型协程的状态协程的挂起await_readyc++协程类型ResultCoroutine(){std::cout<<1<<std::endl;co_awaitstd::suspend_always{};std::cout<<2<<std::endl;std::cout<<3<<std::endl;co_awaitstd::suspend_always{}......
  • C++文件输入输出的简单实现(Debug)
    1.前言:        文件输入输出是个很有用的东西,有时比赛时要有:要求使用文件输入输出,还有时候……    遇到这种时间限制非常恶心的题目:手动测试会有误差……    文件输入输出是个很好的选择!2.写法:C    C语言的写法有点复杂,涉及文件指针,本文不......
  • C++类型转换
    C++类型转换静态转换:​ 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换//指针voidtest02(){ Father*f=NULL; Son*s=NULL; //向下转换不安全 Son*s1=static_cast<Son*>(f); //向上转换安全 Father*f1=static_cast<Father*>(s); //没有继......
  • windows下c++遍历各个磁盘的所有文件,不知道为什么FindFirstFileA文件会报错,进而程序退
    下面的程序还有一些问题,比如360的一些目录就用FindFirstFileA函数打开错误;还有  C:\Windows\System32\WebThreatDefSvc ,属性只有 DIRECTORY,用函数 _access检查也没有问题,但是就是用FindFirstFileA打开的时候错误;至今没有想到解决办法,只能临时跳过这种目录。 #include......
  • C++ Builder使用FMX多平台框架
    C++Builder使用FMX多平台框架C++Builder使用FMX多平台框架C++Builder使用FMX多平台框架......
  • Effective C++ 第一章:让自己习惯C++
    EffectiveC++第一章:让自己习惯C++引言最近在阅读这本《effectiveC++改善程序与设计的55个具体做法》这本书,为了以后忘记的时候回顾,写一些笔记,每次笔记大概记录一个章节的内容。条款1.视C++为一个语言联邦C++最早只是C语言的扩充,在C基础上加上了面向对象特性,但是发展了很多......
  • C++多线程 第五章 C++内存模型和原子类型
    第五章C++内存模型和原子类型无论其他语言如何,C++是一门系统编程语言.委员会希望不再需要一个比C++低级的语言.内存模型基础C++程序中所有的数据均是由对象(object)组成的.C++标准定义对象为"存储区域",经管它会为这些对象分配属于它们的类型和生存期.无论什么类型,对象......