首先贴一个非常简洁却不简单的代码:
Java(jdk1.6) 代码 (C++代码类似,采用GNU的g++编译器)
public class Test{
public static void main(String[] args){
int a=0;
a = a++;
System.out.println(a);
}
}
思考一个问题,这个程序a的输出是多少呢?
… …
最开始的想法是这样的,++自增运算符在这里是后缀式,应该是a赋值给a之后,a再自增一次,即首先a=a,然后a++(a=a+1).如此,最后a的输出值应该是1.
但是,不管是C++(g++编译器)还是Java(jdk1.6),运行的结果让我很惊讶,a的输出为0!这是为什么?csufox经过一段时间的思考,得出了以下的一些认识.
搜索了很多资料,网上有人给出的解释大致如下:++运算符的优先级高于赋值运算符,在程序运行a++时,a的值首先是赋值给一个拷贝或者说临时变量(按值传递,底层实现),即temp=a(即temp=a=0),然后a执行自增运算(运算后a的值为1),最后将这个拷贝(此时拷贝的值为0)作为(a++)整体的值赋值给a(赋值后a的值有重新从1变为0),所以最终的a的值输出为0.即a=a++;语句等价于 a=(temp=a,a+=1,temp);
但是这个解释实在是牵强,底层依然不清楚是具体怎么做的,为什么需要有临时变量?并不能让人信服.下面csufox将从Java的字节码指令来更清楚地了解其细节.
用javap命令反编译上述代码的字节码文件,得到如下信息(附解释):
D:\java>javap -c 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."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0 //将常量'0'push入操作数栈(operand stack,与普通栈不同)
1: istore_1 //将常量'0'存储到栈(注意不是堆,局部变量存储在栈中)
2: iload_1 //将常量'0'载入到操作数栈
3: iinc 1, 1 //在栈中将a增1,a从'0'变为'1'
6: istore_1 //在操作数栈中将常量''重新存储到栈,a从'1'变回'0'
7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
14: return
}
而看看a=++a;的字节码指令:(该代码的a的输出显然是1)
Code:
0: iconst_0
1: istore_1
2: iinc 1, 1 //不同点*
5: iload_1 //不同点*
6: istore_1
7: getstatic
10: iload_1
11: invokevirtual
14: return
我们可以看出不同点就是一个是先载入再自增运算;一个是先自增运算后,再载入新值.
综上可知,iinc字节码指令每次执行时都是从栈中直接执行,而不是在操作数栈中执行.
- 在i=i++的情况下,变量a已经在栈中改变,但是在操作数栈中依然保留原值;
- 在i=++i的情况下,变量a已经在栈中改变,但是在操作数栈中载入的是改变后的新值.
以上是Java对代码输出的解释.C++的解释依然不得而知,将来csufox准备看汇编吧.
参考:
Java字节码及字节码指令: http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/
Java虚拟机规范: http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html
细节决定深度
转自:http://www.csufox.com/a-plus-plus.html
相关推荐
31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip31.java自增自减运算符.zip...
C语言的自增++,自减--运算符对于初学者来说一直都是个难题,甚至很多老手也会产生困惑,最近我在网上看到一个问题: #include void main() /*主函数*/ { int a,b,c,d; a=5; b=5; c=...
一个保险箱密码保护程序 , 有10次密码输入机会,提示剩余尝试次数, 连续10输入错误密码自动关闭, 输入正确的密码给出提示。
自增/自减运算符 目录 课程导入 掌握自增/自减运算符的计算 能够熟练使用自增/自减运算符 自增/自减运算符 基本规则: 作用:在对一个变量做加 1 或减 1 处理时,可以使用 ++ 或 --。 ++ 或 --是单目运算符,放在操作...
C语言自增运算符的置于变量前和变量后的区别与理解自加自减运算符的概念:在普通语句定义并用printf函数输出结果for循环中作为判断条件结语Reference 自加自减运算符的概念: 自增自减运算符存在于C/C++/C#/Java/...
C语言中的自增自减运算符
Java语言中自增、自减运算符解析.pdf
解析C语言中自增自减运算符.pdf
浅析C语言中自增自减运算符的使用问题
C语言中自增自减运算符的使用.pdf
C语言中自增自减运算符教学探究.pdf
试析C语言中的自增自减运算符.pdf
C语言自增自减运算符的解析与应用.pdf
关于C语言自增自减运算符的灵活使用.pdf
sizeof运算符的使用,自增和自减运算符的使用,显示自增自减运算符对3作用时得到的值,显示自增自减运算符对3作用后得到的值
浅谈C语言中自增自减运算符的应用.pdf
C语言中自增自减运算符的应用与解析.pdf
C语言中自增自减运算符在表达式和函数中的应用.pdf
浅谈自增自减运算符在C语言中的应用.pdf