📄 java_plus_minus.htm
字号:
2 x is incremented. x = 2 and temp = 1. <br>
3 the value of the temp register is assigned to the LHS. x = 1<br>
<br>
<font color="#FF0000">【中国Java联盟网友SuperMMX的解释:】<br>
关于后 ++ 运算 </font></p>
<p>By SuperMMX </p>
<p>以下所指的 ++ 运算都指后 ++ 运算. </p>
<p>int x = 0; <br>
x = x++; </p>
<p>x 的值在 java 和 c 中的不同. </p>
<p>看以下程序: </p>
<p>Test.java </p>
<p>public class Test <br>
{ <br>
public static void main(String[] args) <br>
{ <br>
int i = 0; <br>
i = i ++; <br>
System.err.println(i); <br>
System.exit(0); <br>
} <br>
} </p>
<p>javap -c Test </p>
<p>Compiled from Test.java <br>
public class Test extends java.lang.Object { <br>
public Test(); <br>
public static void main(java.lang.String[]); <br>
} </p>
<p>Method Test() <br>
0 aload_0 <br>
1 invokespecial #1 <br>
4 return </p>
<p>Method void main(java.lang.String[]) <br>
0 iconst_0 <br>
1 istore_1 <br>
2 iload_1 <br>
3 iinc 1 1 <br>
6 istore_1 <br>
7 getstatic #2 <br>
10 iload_1 <br>
11 invokevirtual #3 <br>
14 iconst_0 <br>
15 invokestatic #4 <br>
18 return </p>
<p>前面是 javap 反编译出来的字节码. 我们所关心的是 main 中 <br>
0 - 10 行. </p>
<p>首先我们必须对 Java 虚拟机的机制有一些了解, java 的虚拟机主要是基于 <br>
栈的一种模拟机. 通常有这样几种结构: 累加器结构, 通用寄存器结构, 存储器-存储器结构, <br>
栈结构. 这里只说明一下栈结构的工作方式. </p>
<p>栈顾名思义, 就是先进后出, 只能对栈顶元素进行操作. 可能的操作比如进栈, 出栈, +, - <br>
*, / 等等. 举个简单的例子来说, 下面的伪指令: </p>
<p>push a <br>
push b <br>
add <br>
pop c </p>
<p>栈的变化是这样的: </p>
<p>| | | | | | | | | | <br>
| | | | | b | | | | | <br>
|___| |_a_| |_a_| |_a+b_| |___| </p>
<p>如果 a = 1, b = 2, 那么 c 最后等于 3. </p>
<p>Java 中的指令非常多, 不过也就是这些基本的东西所组成. 我们来看一下以上指令 <br>
0 iconst_0 常数 0 进栈 <br>
1 istore_1 把栈顶元素 pop 出来, 存储在 #1 变量中 (也就是 i) <br>
2 iload_1 i 的值进栈 <br>
3 iinc 1 1 将 #1 (i) 加 1, 前一个 1 是变量的 index, 后面的 1 是增加的常量 <br>
6 istore_1 把栈顶元素 pop 出来, 存储在 #1 变量中(i) <br>
7 getstatic #2 <br>
10 iload_1 <br>
11 invokevirtual #3 </p>
<p>从上面的解释我们可以看出, i 最终的值是 0. </p>
<p><br>
相应的 c 程序如下: </p>
<p>#include </p>
<p>int main() <br>
{ <br>
int i = 0; <br>
i = i ++; <br>
printf("%d\n", i ); <br>
return 0; <br>
} </p>
<p><br>
0x8048440 : push %ebp <br>
0x8048441 : mov %esp,%ebp <br>
0x8048443 : sub $0x18,%esp <br>
0x8048446 : movl $0x0,0xfffffffc(%ebp) <br>
0x804844d : mov 0xfffffffc(%ebp),%eax <br>
0x8048450 : mov %eax,0xfffffffc(%ebp) <br>
0x8048453 : incl 0xfffffffc(%ebp) <br>
0x8048456 : add $0xfffffff8,%esp <br>
0x8048459 : mov 0xfffffffc(%ebp),%eax <br>
0x804845c : push %eax <br>
0x804845d : push $0x80484d4 <br>
0x8048462 : call 0x8048344 <br>
0x8048467 : add $0x10,%esp <br>
0x804846a : xor %eax,%eax <br>
0x804846c : jmp 0x8048470 <br>
0x804846e : mov %esi,%esi <br>
0x8048470 : leave <br>
0x8048471 : ret </p>
<p><br>
最重要的是 main + 6 到 main + 19 部分. 也是我们所关心的部分. </p>
<p>: movl $0x0,0xfffffffc(%ebp) 给 i 赋值为 0 <br>
: mov 0xfffffffc(%ebp),%eax 把 i 的值赋给 eax 寄存器 <br>
: mov %eax,0xfffffffc(%ebp) 把 eax 寄存器的值赋给 i (计算完毕, 没有其他计算) <br>
: incl 0xfffffffc(%ebp) 将 i 加 1. </p>
<p>从中可以看出, i 最后的值是 1; </p>
<p><br>
到现在为止, 我们粗略看了一下 Java 和 C 中对于 ++ 运算的不同. 但是还并不明显. </p>
<p><br>
我们再看一个例子: </p>
<p>public class Test <br>
{ <br>
public static void main(String[] args) <br>
{ <br>
int i = 1, j = 2; <br>
i = (j ++) + (i ++); <br>
System.err.println(i); <br>
System.exit(0); <br>
} <br>
} </p>
<p> 0 iconst_1 <br>
1 istore_1 <br>
2 iconst_2 <br>
3 istore_2 <br>
4 iload_2 <br>
5 iinc 2 1 <br>
8 iload_1 <br>
9 iinc 1 1 <br>
12 iadd <br>
13 istore_1 </p>
<p><br>
#include </p>
<p>int main() <br>
{ <br>
int i = 1, j = 2; <br>
i = (j++) + (i++); <br>
printf("%d\n", i ); <br>
return 0; <br>
} </p>
<p>0x8048446 : movl $0x1,0xfffffffc(%ebp) <br>
0x804844d : movl $0x2,0xfffffff8(%ebp) <br>
0x8048454 : mov 0xfffffff8(%ebp),%eax <br>
0x8048457 : mov 0xfffffffc(%ebp),%edx <br>
0x804845a : lea (%edx,%eax,1),%ecx <br>
0x804845d : mov %ecx,0xfffffffc(%ebp) <br>
0x8048460 : incl 0xfffffffc(%ebp) <br>
0x8048463 : incl 0xfffffff8(%ebp) </p>
<p>从上面的例子我们可以看出, 在 Java 和 C 中, ++ 运算的语义是有所不同的, Java 中 <br>
++ 运算是在赋值运算之前完成的, 而 C 中是在赋值预算之后完成的. </p>
<p>测试环境: </p>
<p>Debian 2.2r3 <br>
blackdown jdk 1.3.1 <br>
gcc 2.95.4 <br>
gdb GNU gdb 5.0.90-cvs (MI_OUT) </p>
<p><font color="#FF0000"> </font></p>
<!-- #EndEditable --></td>
<td width="20"> </td>
</tr>
<tr>
<td width="20" height="11"> </td>
<td width="541" height="11"><!-- #BeginEditable "7" --><!-- #EndEditable --></td>
<td width="101" height="11">
</td>
<td width="20" height="11"> </td>
</tr>
</table><div align="center"> <br>
</div>
</td>
</tr>
</table>
<div align="center">
<br>
</div>
</body>
<!-- #EndTemplate -->
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -