今天遇到一段程序代码,如下:
int j = 0;
for(int i = 0;i < 100;i++) {
j = j++;
System.out.println(j);
}
就是这段程序会输出什么,当时不假思索便认为
输出会是1,2,3,4,5,6,7,8,9,10。
编译运行的结果却是0,0,0,0,0,0,0,0,0,0。即10个零。
百思不得其解。
当时给的解释是i = i++ 和下面这段程序是相同的效果:(记不清楚了)
int i = 0;
int tmp = i;
i = i + 1;
i = tmp;
想想还是比较迷糊,于是回来反编译了一下一些代码,发现一些问题:int i = 0;
i++;
这个反编译出来的是:
0: iconst_0
1: istore_1
2: iinc 1, 1
5: returnint i = 0;
i = i + 1;
反编译的结果是:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_1
4: iadd
5: istore_1
6: returnint i = 0;
i = i ++;
反编译的结果是: 0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: return从这三段反编译的代码来看,i++ 的效率比 i = i + 1 的效率高出很多。
但是后面两段看起来比较晕。
请大虾指教。
int j = 0;
for(int i = 0;i < 100;i++) {
j = j++;
System.out.println(j);
}
就是这段程序会输出什么,当时不假思索便认为
输出会是1,2,3,4,5,6,7,8,9,10。
编译运行的结果却是0,0,0,0,0,0,0,0,0,0。即10个零。
百思不得其解。
当时给的解释是i = i++ 和下面这段程序是相同的效果:(记不清楚了)
int i = 0;
int tmp = i;
i = i + 1;
i = tmp;
想想还是比较迷糊,于是回来反编译了一下一些代码,发现一些问题:int i = 0;
i++;
这个反编译出来的是:
0: iconst_0
1: istore_1
2: iinc 1, 1
5: returnint i = 0;
i = i + 1;
反编译的结果是:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_1
4: iadd
5: istore_1
6: returnint i = 0;
i = i ++;
反编译的结果是: 0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: return从这三段反编译的代码来看,i++ 的效率比 i = i + 1 的效率高出很多。
但是后面两段看起来比较晕。
请大虾指教。
j=j++; 执行后在System.out.println(j);中j的值为0当然输出是0 0 0 0 了
如果把j=j++; 改为j=++j;那么先进行++j操作得到j=1;然后输出则得到的是 1
就可以得到 1 2 3 4 5 6 7 8 ...的结果
但是同样在c语言中运行
main()
{
int i,j;
j=0,i=0;for(i=0;i<100;i++)
{
j=++j;
printf("j=%d ",j);
}
}
和main()
{
int i,j;
j=0,i=0;for(i=0;i<100;i++)
{
j=j++;
printf("j=%d ",j);
}
}却得到了相同的结果 1 2 3 4 5 6 7...
int j = 0;
for(int i = 0;i < 10;i++) {
j++;
System.out.println(j);
System.out.println(i);
}
j打印出的就是我们预想的1,2,3,4,5,6,7,8,9,10
i打印出的却是0,1,2,3,4,5,6,7,8,9
也就是j++和i++在不同的作用域导致不同的结果了再把程序改一下:
int j = 0;
int c=0;
for(int i = 0;i < 10;i++) {
c=j++;
System.out.println(c);
}
实际上这边输出的,其实就是上例的i,也是0,1,2,3,4,5,6,7,8,9
而 int j = 0;
int c=0;
for(int i = 0;i < 10;i++) {
j=j++;
System.out.println(c);
}
之所以输出全零是因为,j=j++,右边的j++每次都得到零,自加1,它把零赋给了左边的j!每个循环都是如此!
输出的结果可以理解,但楼主的反编译代码却晕,看不懂!
换句话说,
while(true){
i=i++;
}
永远执行i的值恒等于i的初始值,即使不是0也一样!下面我把过程写一下i=0;//假设此时内存地址为0x12345678
i=i++;//系统新开内存地址0x99999999,存放i原始值0,然后0x12345678的存放数据+1操作
//此时0x12345678=1,0x99999999=0,但是上一步是先给值,所以i的内存地址是0x99999999=0;所以i=0,但是,如果是
i=0;
i++;
此时i=1,因为0x99999999处新开辟的内存地址没有给任何引用,所以被丢弃了!i继续使用0x12345678处值
++运算符的优先级比=运算符要高,也就是说,首先计算++,然后计算=那么上面的j=j++;就可以看作是首先计算j++,然后将这个表达式的返回值赋值给j。
j++进行计算的时候,会让j字加一,也就是从0变成1;
但是,j++的返回值是0,因为++运算符放在后面时是先取值作为返回值备用,然后自加;
最后,把这个返回值(也就是0),通过=运算符赋值给j,也就是让j又变成了0。至于你的反汇编……
也就是说这个CPU里面的存储器是stack结构的,特点是好像一个大坑,先掉进去的最后才能爬出来。
那么我们看一下你的反汇编代码。int i = 0;
i++;
这个反编译出来的是:
0: iconst_0 将常数0推入stack
1: istore_1 从stack中弹出一个值(这个值显然是刚刚推入的0)存储到变量索引为1的位置(也就是我们的i)
2: iinc 1, 1 将变量索引为1的变量(也就是我们的i)值增加1,现在i变成了1
5: return 返回int i = 0;
i = i + 1;
反编译的结果是:
0: iconst_0 将常数0推入stack
1: istore_1 从stack中弹出一个值(这个值显然是刚刚推入的0)存储到变量索引为1的位置(也就是我们的i)
2: iload_1 将变量索引为1的变量值推入stack,现在stack里面只有一个值: 0
3: iconst_1 将变量1推入stack,现在stack里面有两个值,依次(推入次序)为: 0, 1
4: iadd 从stack中弹出两个值进行相加,并将结果推入stack,现在stack里面又剩下一个值: 1 (因为0 + 1 = 1)
5: istore_1 从stack中弹出一个值(这个值显然是刚刚算出的1)存储到变量索引为1的位置(也就是我们的i),现在i变成了1
6: return 返回int i = 0;
i = i ++;
反编译的结果是: 0: iconst_0 将常数0推入stack
1: istore_1 从stack中弹出一个值(这个值显然是刚刚推入的0)存储到变量索引为1的位置(也就是我们的i)
2: iload_1 将变量索引为1的变量值推入stack,现在stack里面只有一个值: 0
3: iinc 1, 1 将变量索引为1的变量(也就是我们的i)值增加1,现在i变成了1
6: istore_1 从stack中弹出一个值(这个值应该是前面2的位置推入的0)存储到变量索引为1的位置(也就是我们的i),现在i又变成了0
7: return 返回
这就是结果的原因。参考了这个网站:
http://www.jspcn.net/htmlnews/11049384431711149.html
j=j++;
System.out.println(c);
}
1.j在自增之前将值副给j,此时j还是0,下一次循环又重复了这个过程,所以输出都是0
2. short j=0;
j=j+1;//编译通不过,必须强制类型转换
但是:
j+=1;//可行的,不管是向类型小的转换都可以
不过c语言的结果比较让人费解(c语言标准对i=i++这个没有规范,也就是说不同的编译器可以实现不同)
基本上已經知道是什麽情況了。i = i++在C中是未定义的情况,可以进行如下操作:
1) i++; i = i
2)temp = i; i++; i=temp 而Java明確規定了 i = i ++ 是進行第二种操作(據説JVM規範上有,我身邊沒這書,不知是否是這樣),這樣就不能理解為什麽是 0 了 。
http://community.csdn.net/Expert/topic/4197/4197388.xml?temp=.41914
http://java.sun.com/docs/index.html最新的Java Language Specification
http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html最新的Java Virtual Machine Specification
http://java.sun.com/docs/books/vmspec/2nd-edition/jvms-java5.html所以,不需要花钱去买了。这东西本来就是免费的。