再次分析i++與i--
之前一篇 i++與i--的分析 ,說明了在執行i++或i--操作時,應運用所學的計算機知識:資料操作的原理,應理解清楚運算元和棧的關係。當時也沒整理清楚。最近又遇到i++和i--相關的題。又把自己給整懵了。在看了解析class反編譯檔案 後,也去分析class檔案,最終算是真正弄明白了i++和i--。
在要理解i++和i--的原理之前,需要明白java的棧和堆方面的知識。這裡就不再介紹棧和堆了。下面主要貼圖說明i++的實現原理。只要分析清楚了i++,i--就不在話下。
下面看java源程式:
package com.michael.test;
/**
* @author michael
* @email [email protected]
* @version 1.0
*/
public class TestMain {
public static void main(String[] args){
int i = 0 ;
i = i++ + ++i;
System.err.println(i);
}
}
在dos下先編譯該檔案javac TestMain.java
再執行javap -verbose TestMain輸出如下
Compiled from "TestMain.java" public class com.michael.test.TestMain extends java.lang.Object SourceFile: "TestMain.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #5.#14; // java/lang/Object."<init>":()V const #2 = Field #15.#16; // java/lang/System.err:Ljava/io/PrintStre const #3 = Method #17.#18; // java/io/PrintStream.println:(I)V const #4 = class #19; // com/michael/test/TestMain const #5 = class #20; // java/lang/Object const #6 = Asciz <init>; const #7 = Asciz ()V; const #8 = Asciz Code; const #9 = Asciz LineNumberTable; const #10 = Asciz main; const #11 = Asciz ([Ljava/lang/String;)V; const #12 = Asciz SourceFile; const #13 = Asciz TestMain.java; const #14 = NameAndType #6:#7;// "<init>":()V const #15 = class #21; // java/lang/System const #16 = NameAndType #22:#23;// err:Ljava/io/PrintStream; const #17 = class #24; // java/io/PrintStream const #18 = NameAndType #25:#26;// println:(I)V const #19 = Asciz com/michael/test/TestMain; const #20 = Asciz java/lang/Object; const #21 = Asciz java/lang/System; const #22 = Asciz err; const #23 = Asciz Ljava/io/PrintStream;; const #24 = Asciz java/io/PrintStream; const #25 = Asciz println; const #26 = Asciz (I)V; { public com.michael.test.TestMain(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 8: 0 public static void main(java.lang.String[]); Code: Stack=2, Locals=2, Args_size=1 0: iconst_0 1: istore_1 2: iload_1 3: iinc 1, 1 6: iinc 1, 1 9: iload_1 10: iadd 11: istore_1 12: getstatic #2; //Field java/lang/System.err:Ljava/io/PrintStream; 15: iload_1 16: invokevirtual #3; //Method java/io/PrintStream.println:(I)V 19: return LineNumberTable: line 11: 0 line 12: 2 line 13: 12 line 14: 19 }
這裡主要分析對資料操作部分。其他部分可參考前一篇 解析class反編譯檔案
下面貼圖說明資料的操作過程:
經過上面的分析,可以知道在對資料執行基本運算時都是對運算元棧中的資料進行操作。而對儲存在堆中的變數本身沒有影響。
看下面的程式碼:
程式碼一:
public class TestMain {
public static void main(String[] args){
int i = 0 ;
i = ++i + i++ ;
System.err.println(i);
}
}
程式碼二:
public class TestMain { public static void main(String[] args){ int i = 0 ; i = i++ + ++i; System.err.println(i); } }
程式碼一二的輸出結果都為2。通過上面的分析就能理解為什麼等於2了。
相關推薦
再次分析i++與i--
之前一篇 i++與i--的分析 ,說明了在執行i++或i--操作時,應運用所學的計算機知識:資料操作的原理,應理解清楚運算元和棧的關係。當時也沒整理清楚。最近又遇到i++和i--相關的題。又把自己給整懵了。在看了解析class反編譯檔案 後,也去分析class檔案,
i++與++i的區別+彙編分析
這是很多初級C/C++程式設計師最容易碰到的一個問題這裡來給大家簡明摘要的給大家講解一下:i++i++是後遞增有如下語句:int i = 0; printf("%d,",i++);在列印輸出時會發現是0,上面也說了i++是後遞增其意思就是在一條指令執行完成之後才會去對i這個變
【java】i++與++i、i--運算
log 原理 ring 自加 clas rgs stat static system 1 package test; 2 3 //i++與--i運算 4 public class test { 5 6 public static void main
關於i++與++i的學習討論!
tor 結果 知識點 dword asm i++ span -c ofo 先談容易的知識點 區別兩個 1、 i++ 返回原來的值,++i 返回加1後的值。 2、 i++ 不能作為左值,而++i 可以。 重點說下第二點。首先解釋下什麽是左值 左值是
在Java中for迴圈的++i與i++問題
###首先指出二者在用法上並無區別: 首先看一段程式碼: int i; for (i = 0, j = 0; i < 2, j < 2; i++, ++j) { printf("i = %d ", i); printf("j = %d\n"
【轉載】 for迴圈中i++與++i的效率探究
原文連結:https://blog.csdn.net/zy1691/article/details/4849808?utm_source=blogxgwz1 for(int i=0;i<=50;i++) 我們經常會使用這樣的程式碼來做迴圈,一般在for迴圈中習慣於
java裡的i++與i=i++會有怎樣的結果?JVM做了什麼?
先來看下這段程式碼: public static void main(String[] args) { int count = 0; for (int i = 0; i < 10; i++) { count=count++
Java中i++與++i的區別
表示式結果: i++,表示式的結果為i ++i,表示式的結果為(i+1) 空間 i++,會申請一個臨時空間來儲存i的值作為表示式的結果 ++i,運算之後i值即為表示式結果,不申請臨時空間
i++與++i區別
i++與++i主要區別有兩個: 1)i++返回加1前的值,++i返回加1後的值; 2)i++不能作為左值,而++i可以。 注:★左值是對應記憶體中有確定儲存地址的物件的表示式的值,而右值是所有不是左值的表示式的值。(引用自中文維基百科【左值引用】) ★能
Ubuntu環境下++i與i++
#include <stdio.h> int main() { int i = 0; int s = 0; // s = i++ + ++i + i++;//i=3,s=6 // s = i++ + ++i + ++i;//i=3,s=
Python中“i+=i與i=i+i”的區別梳理:(引用、記憶體、可變引數、不可變引數)
Python中“i+=i與i=i+i”的區別梳理 一、 "i+=i"執行時資料記憶體的變化 當num+=num執行時,num原引用的記憶體空間中,根據空間中儲存的引數的資料型別是否為可變型別而進行變化,***可變的引數資料型別***有:列表、字典;***不可變引
Java學習筆記——i++與++i問題
不同情況分析 邏輯運算子,++/--在前則先執行++/--。在後面則後執行++/-- k++是執行邏輯判斷符號,之後再進行k的遞增 int k=3; k++==3; //結果為true ++k則是先遞增,後判斷 int k=3; ++k==3;//結果為false PS:在輸出語句中也
js裡面for迴圈的++i與i++
首先我們應該都知道++i與i++的區別是: ++i 是先執行 i=i+1 再使用 i 的值,而 i++ 是先使用 i 的值再執行 i=i+1; 然後我們也知道for迴圈的執行順序如下: for(A;B;C){ D;}進入迴圈執行A;//只是進入的時候執行.執行B;//條件為真才執行D,不然就跳出for
java中的i++與++i有什麼區別?
剛開始接觸時,做了一些小測試,還以為這兩個沒有什麼區別。 public class OperatorDemo { public static void main(String[] args){ int a = 10; a++; System.o
c++ 中 `++i` 與 `i++` 在運算表示式中的優先順序
在算術表示式中,優先順序高的運算子先運算,優先順序低的運算子後運算,不同的優先順序直接影響表示式的計算結果。 1. 說明 gcc中 gcc中的加法運算表示式中,是按照從左到右按順序,如果運算子兩邊有++i運算元,就先進行++i操作,然後進行加法運算;
2.3 i++/i--與++i/--i的運算
一、i++/i--: i先參與運算,運算完成後自加/減1; public class Test{ public static void main(String[] args){ // 【1】 int i = 10;
i++與++i效率比較
1.對於i是內建型別,效率無差別,編譯器會自動優化 2.對於i為非內建型別,效率會存在不同,主要體現在其功能作用不同,++i是將i值自增後返回,而i++是返回(i+1)的臨時變數,同時將i自增。 可以猜想其過載操作符實現邏輯與下面程式碼類似: className class
C/C++面試題:i++與++i哪個效率更高?
解析: 在這裡宣告,簡單的比較字首自增運算子和字尾自增運算子的效率是片面的,因為存在很多因素影響這個問題的答案。首先考慮內建資料型別的情況:如果自增運算表示式的結果沒有被使用,而是僅僅簡單的用於增加一員運算元,答案是明確的,字首法和字尾法沒有任何區別,編譯器的處理都應該是
java中i++ 與 i=i++的區別
記得大學剛開始學C語言時,老師就說:自增有兩種形式,分別是i++與++i,i++表示的是先賦值後加1,++i是先加1後賦值。我們來看下下面的例子: public class Client { public static void main(Stri
關於i++,++i與i+=1的效能
曾經寫程式碼測試,估計也有不少人做過這種傻事,最終“測不準”,從內部著手分析吧。 1.對於int i=0;,表示式 1)i++ 2)++i 3)i+=1 本身沒什麼區別,最終都編譯成"iinc 1,1" 使用i變數時: --------------- i++; ------