話說最近又看到一些小朋友發問同樣的爛問題,大概是同班同學吧。

猜猜會印出什麼?

int a = 10, b = 20;
a = a++;
b = b--;
printf("%d %d\n", a, b);

這樣的題目以及種種變形總是一次又一次在各大程式討論區出現,有時是學校作業、有的是爛書後面的練習、甚至正式考試也有人出過,好像永遠不會死。真不知道出這些題目的人希望我們的小朋友學會什麼?

事實上這段程式碼會導致未定義行為,在 Dev C++ 會印出
10 20

在 VC2008 則是
11 19

更糟糕的是,總有一群自以為是的蠢才,拿著自己想像出來的 C&C++ 規則對小朋友們解釋出一番大道理,搞不好心裡還以為其他人太遜答不出來。連 C 和 C++ 標準委員會的人都擺明了不想去定義的東西,竟然還有人掰得出來,真厲害。

雖 C 和 C++ 兩種程式語言都定義了 a++ 是「先取值,再加1」,卻都沒規定何時「才」加,編譯器必須自行決定適當時機。類似的變形 x[i] = i++; 同樣屬未定義行為。

還有一個常見的是 function call:

int c = 0;
printf("%d %d %d\n", c++, c++, c++);
printf("%d %d %d\n", c=3, c--, c--);

上面這段程式碼也是未定義行為,在VC2008甚至連 debug 和 release都會跑出不同結果。C++ 標準只規定所有的參數都必須在 call 之前算出來,但計算順序卻是擺明著不想規定。

有點概念的人可能會知道函數參數 push 的順序是由 calling convention 決定,雖然這並不是標準的一部分,不過還算是明確可遵循的法則。但 calling convention 也只管 push 的順序,參數演算的順序卻完全不干 calling convention 的事。

誇張的是在網路上可以看到有些人侃侃而談:「因為 C、C++ 都是由左而右計算 blah blah....」,連ISO的規格書都沒有沒規定,真不知道這些規則哪裡生出來的。

這些教學、寫書、出考題的人到底意欲為何呢?我想是

1. 他們希望培養更多能製造意義不明程式碼的人才。
2. 他們的學校、公司已經有一堆這樣的程式碼,迫於無奈所以希望培養出(或錄取)有能力維護的人。
3. 因為他們從來沒寫過真正的軟體,也沒什麼更有價值的東西可以教,這已經是他們的得意伎倆。
4. 他們希望藉由這些案例教導學生不要寫出意義不明程式碼。

我希望原因是4,不過我猜3很可能才是主因。

novus 發表在 痞客邦 PIXNET 留言(0) 人氣()