這是我去面試時的考題,

當時笨笨的,一直想不出來

(在此感謝建安,崇德及86的幫忙)

VB語法:

Dim x, y, z, n As Integer
x = 0
y = 0
z = 0

For n = 10 To 0 Step -1
Console.WriteLine(y)
z = x + y
If z = 0 Then z += 1
x = y
y = z
Next

——————————————————————————–

Java:

int x = 0,y = 0,z = 0;
int size = 10;
while((size–)>= 0){
System.out.println ;
z = x+y;
if(z == 0)++z;
x = y;
y = z;
}

新增回應
上午 11:32 | 永久連結 | 引用通告 (0) | 發佈至您的部落格 | CODING

永久連結 關閉

http://spaces.msn.com/jason695/blog/cns!1BF4A629EA6C6E8E!1196.entry

從 i=i++; 談程式師容易犯的錯!

轉貼自﹝工程師的家﹞

code:——————————————————————————–
i=0;
i=i++;
——————————————————————————–
這樣的程式,最後 i 的值會是多少?0 還是 1 或其它值?
我在網路上看過幾個類似的問題,回覆的答案也是莫衷一是。
對大部份的 C/C++ Compiler測試的結果是 1,
有人把它拿到 java 上測試,發現結果是 0 。
但 C/C++ 和 java 對這樣表示式的計算規則是一樣的啊!
是java不好?還是 C/C++ 錯了?事實上,都不是,
是程式寫得有問題!

ANSI C/C++ 運算式(expression)有一個但書:
如果一個左值(l-value)在運算式中被改變了兩次以上,除非運算子
能保證其計算次序,否則運算式的結果是未定義的

很明顯的 i 在運算式中被改變了兩次,所以:
運算後 i 的結果在ANSI C/C++的規格是未定義的,它依compiler 所用的運
算式演算法不同而有不同的結果,用你手上的C++ Compiler,i的結果可能
是0或是1甚至是其它的值,但不表示其它家的C++compiler 會有一樣的結
果; 甚至你手上C++的下一個版本都不保證會和現在一樣。因為它們都未違
反ANSI 的法律!

很多程式員並不熟讀程式語言的細節而容易犯下這樣的錯,原來跑得好好的
程式在compiler換上新版本後出現了問題。通常直覺的會去怪”新版本”的
compiler有bug!但十有八九問題是出在自己的程式。

”一個左值(l-value)在運算式中被改變了兩次以上,除非運算子 能保證
其計算次序,否則運算式的結果是未定義的”
這在C/C++原始的定義是這樣的:
一個運算式中若含有子運算式,子運算式的計值次序是未定義。
(未定義的意思是ANSI 未規範,編譯器可自行依演算法之差異而便宜行事)
對 i=i++; 這個運算式來說它分成
i=i;//<---主運算式 i=i+1;//<---子運算式 兩個運算式 因為子運算式(i=i+1)計值次序未定義,所以主運算式的右值 i 到底是新值或 舊值便無法確定,所以最後指派到i的值便未定義。 那麼什麼運算子可以保證子運算式的計值次序?就是”循序”運算子:逗號 (,) 像這樣的式子是正確的運算式: j=i++, i=j+2; 循序運算子保證其左邊會先於右邊計值。 注意到在C/C++裡只有運算式中的逗號是循序運算子,不是所有的逗號都 是循序運算子。 例如呼叫函式: FuncCall(i, j*i++); 這程的函式的呼叫是錯的,兩個引數中間的逗號是”分隔符號”不是”循序 運算子”。C/C++也不保證引數的計值次序,結果是第一個引數值是不確定的。