匪夷所思的“i=i++”

来源:互联网 发布:学编程好就业吗 编辑:程序博客网 时间:2024/04/28 13:20

不管是C,还是C++,还是JAVA,相信“i++”和“++i”一直是初学者最难区别的2个运算符

大家所熟知的区别就是:

“i++”意味着“变量i先被使用,之后再进行自加1操作”,而“++i”则意味着“变量i先进行自加1操作,之后再被使用”。

 

最近看到这样一段JAVA代码:

估计好多人一看到这段代码,就不加思索的自信的回答,输出肯定是“1”;而这个“1”也正好符合了在我们脑海里根深蒂固的“变量i先被使用,之后再进行自加1操作”的原则。但是出乎意料的是,输出结果却为“0”。

 

那这段代码在C里执行又是怎样的结果:

再看一段C程序代码:

输出:i=1

 

同样都是i=i++,为什么得出的结果会有这么大的差异呢?原来是在编译器上出了问题,java的编译器在遇到i++和i--的时候会重新为变量运算分配一块内存空间,以存放原始的值,而在完成了赋值运算之后,将这块内存释放掉。

下面首先看一下如果是j=i++的情况:

输出:j=0,i=1;
i的原始值存放在后开辟的内存中,最后这个值将赋值给j,这样j=i++后,j就会得到i的值,而i又将自
加,所以,在释放内存之后,原来存放j和i的地方将得到值将是:j(此时的值等于初始i值)和i(i自加后的值)。
而C语言中的i=i++就只是完成i++的内容,所以结论会不同。这种情况说明java和c的处理语法的机制不
同,如果在程序中只输入i++就不会出现这个方面的问题,所以大家在以后的程序中如果使用到i=i++的时候要格外小心,一般只需要用i++就不会有问题了。也难怪有些大公司里的编码规范里不允许使用“i++”或者“i--”之类的代码,只允许使用最通俗易懂的形式“i=i+1”或“i=i-1”了。

 

 

另外,在java lang spec中提到:
1、java运算符的优先级++符是大于=的。
2、The result of the postfix increment expression_r is not a variable, but a value.

后++符表达式的结果是个值而不是一个变量。


也就是说后++符先将自己的值存储起来,然后对变量进行++;再进行赋值操作,也就是将先存储起来的值赋给变量i,这样的操作就导致了i值被置为0了对于C和C++来说
不一样,在讲到m=i++操作时,C语言是先将i的值赋给了m,然后将i值++,这样i=i++的结果自然就是1了,c的实现中是不存在那个中间的值的存储的。由于java和c不同的语言特性,导致了i=i++的不同之处,前面的笔记中已经提到,由于java lang spec中的一些细微规定,导致其运行结果的不同,我们可以用个例子来看i=i++在jvm中实际的运行过程。
源程序test.java:

我们用javap来看其实际的虚拟机指令集:
C:/JBuilderX/jdk1.4/bin>javap -c  -classpath "d:/" test
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   nop
   5:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0 //常数0入栈
   1:   istore_1 //i赋值,常数值出栈
 //至此完成i=0;
   2:   iload_1  //装载变量i,0入栈
 //第2步是特殊的一步,这步将i值先行保存,以备赋值使用
   3:   iinc    1, 1 //变量值增加,栈内值不变
 //至此完成i++
   6:   istore_1 //i赋值,0出栈。
 //至此完成i=i++
   7:   nop  //donothing
   8:   return

}

对比而言,对于i++而言,i=i++指令多了两步,2和6

其实这两步是赋值符号引起的,有意思的是第二步出现的时机,是在iinc之前,这就是因为java lang spec中规定的。

原创粉丝点击