|
阅读:1171回复:12
i++與i--的陷阱
昨天意外發現一個奇怪的現象,i++和i--, 看起來相當簡單~
僞代碼: // i++ int i = 0; i = i++-1; print(i); // i-- int i = 0; i = i---1; print(i); 這裏兩個運算分別進行後, i 分別是多少? 學過C的一眼就能看出, 第一個結果是 0, 第二個結果是 -2. 但是如果是在JAVA裏, 問題出現了~ 以下是測試代碼: // i ++
public class Ipuzzle{
public static void main(String[] args){
int i = 0;
i = i++ -1;
System.out.println("i = "+i);
}
}
// i --
public class Ipuzzle{
public static void main(String[] args){
int i = 0;
i = i-- -1;
System.out.println("i = "+i);
}
}
這時不幸發生了, 輸出的結果居然都是 i = -1 (oops!) 而相同的內容用C描述並且用GCC編譯並運行的結果卻和推測的一樣, 分別是 0 和 -2. 這是什麽原因呢?(為了避免4C的服務器當掉導致偶寫的內容全都泡湯, 先發一下再回複吧-_-#) |
|
|
|
1C#
发布于:2005-10-29 10:47
Re:i++與i--的陷阱
以下是我對上面原因的推測, 可能不對~請達人解釋一下~~
對於C: 運算過程 i = i++-1 可以作以下分解: // i = 0; //前文提到 1. i = 0 - 1 //運算後 i = -1 2. i = i + 1 // i++, 這和平時的理解都是一致的, 運算後 i = -1 而對於java 運算過程 i = i++-1 作這樣的分解: // i = 0; //前文提到 1. int j = 0 - 1; //即 int j = i - 1, 此時虛擬機創建了另一個對象來進行運算 2. i = i + 1; // i ++, 此時 i = 1. 3. i = j; //虛擬機把指向 j 的值的指針作為 i 的指針, 好像說的不是很清楚~`過程如下: 假定在第一步運算的時候創建了另一個對象(j), 那麽運算後的內容就應該是 pointer i ---------------> (int) 1 pointer j ---------------> (int) -1 然後 i 和 j 指針的指向進行了互換, 這樣結果 i 就是 -1 了. 但是為什麽要互換呢? 因為我們要求的數是 i 而不是 j ,事實上我們從來沒有顯式地引入第二個變量, 所以此虛擬機為了服從我們, 就把它們兩個互換了~它總不能告訴我們說"對不起, 我這裏有兩個 i ,你想要我輸出哪一個?" 所以問題就出現了~~ 有這種想法是因為在字符串的改變過程中的操作有些相似 比如說: String str = "hello"; str = "hello Mr.0000"; 實際上現在內存裏有兩個 String 的對象, 分別是 "hello" 和 "hello Mr.0000" 在把 str 的值改到 "hello Mr.0000" 的過程中虛擬機做了以下操作: Create String "hello" //這是第一步, String str = "hello" str ----> "hello" //變量str指向 "hello" Create String "hello Mr.0000" str --> "hello Mr.0000" //把變量str指向新的字符串 "hello Mr.0000", 而舊的"hello"而等待GC來處理. 但是這只是對 Object 的操作, 而至於對 primity(這個單詞好像寫錯了?不好好學習-_-##) 類型數據是不是這樣處理就不清楚了~~ |
|
|
|
2C#
发布于:2005-10-29 10:49
Re:i++與i--的陷阱
任意拿起一本JAVAXXX教程的第一章都會堂皇地說"萬物皆對象"(當然也不排除是在第二章~~). 我倒覺得這裏還有一句話就是萬物皆指針也許更合適一點~~~ |
|
|
|
3C#
发布于:2005-10-29 10:51
Re:i++與i--的陷阱
BTW:
說明一下測試環境: JAVA: JDK1.5 C: 這個偶就不知道了~~單位的服務器,應該是 Suse 的系統~~, GCC的版本也不知道~ |
|
|
|
4C#
发布于:2005-10-29 21:37
Re:i++與i--的陷阱
我是这么理解的
i++ 就是先运算完 再自己加上1 所以 int i = 0; i = i++ -1; // i=0-1=-1 然后自己再运算一次加1=0,但是已经不影响 i++ -1的结果了. 所以说 i 的值就是-1, 这就是i++和++i 的区别吧, 在自己加1上有个顺序问题, 如果换成以下这样,虽然结果还不能是0,但就是这个意思 public class Ipuzzle{ public static void main(String[] args){ int i = 0; int a = i++ -1; System.out.println("a = "+a); System.out.println("i = "+i); } } a=-1 i=1 唉呀呀,反正我就是这个意思,也不知道怎么表达好了,哈哈[em149] [ 2005-10-29 22:18:53 瘦人 修改 ] |
|
|
|
5C#
发布于:2005-10-30 09:17
Re:i++與i--的陷阱
但是c里头的结果可不一样哦~
也就是说在java里, int i = 0; i = i++ -1; 这个运算创建了两个i,而在c里只有一个i~ |
|
|
|
6C#
发布于:2005-10-30 09:41
Re:i++與i--的陷阱
java源于c而高于c[em061] |
|
|
|
7C#
发布于:2005-11-02 09:29
Re:i++與i--的陷阱
还是不习惯java的方式~ |
|
|
|
8C#
发布于:2005-11-03 00:47
Re:i++與i--的陷阱
http://www.wait4c.com/bbs/message.asp?id=168734 |
|
|
9C#
发布于:2005-11-03 18:21
Re:i++與i--的陷阱
哈哈~当年偶才 68 帖就狂妄到口算~~ |
|
|
|
10C#
发布于:2005-11-03 18:23
Re:i++與i--的陷阱
You are modifying a variable in an expression that uses it twice. That's-_-#什么叫没有定义嘛~~ |
|
|
|
12C#
发布于:2005-11-14 12:45
Re:i++與i--的陷阱
周末和同学讨论到这个问题, 觉得用JAVA的 "传值" 的概念更好解释.
把操作符看作是一个 方法, 用传值(与此相对, C/C++中的传引用)的观点正好解释这个问题~ |
|
|