⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 java_plus_minus.htm

📁 写给JSP初级程序员的书
💻 HTM
📖 第 1 页 / 共 2 页
字号:
              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(&quot;%d\n&quot;, 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(&quot;%d\n&quot;, 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">&nbsp;</td>
        </tr>
        <tr> 
          <td width="20" height="11">&nbsp;</td>
          <td width="541" height="11"><!-- #BeginEditable "7" --><!-- #EndEditable --></td>
          <td width="101" height="11"> 
            
          </td>
          <td width="20" height="11">&nbsp;</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 + -