春節期間,一個正在讀電腦系大四的朋友到我這裡聊天,談到C語言的學習時,他說C語言入門容易,精通很難,我表示贊同。他接著舉例說,每次寫一些函數,自己反覆修改後,拿給同學們看時,不是被挑出一些毛病,就是代碼被大量精簡。我說,初學者首要的是要保證代碼的正確性和可讀性,代碼寫多了後,問題自然少了,代碼也較簡潔了,效率也會隨之提高。後來我問他,實現同樣功能,簡潔代碼一定比複雜代碼效率高嗎?他想了一下說,還得看演算法,如果演算法相同,簡潔代碼效率應該高些吧?!我笑了笑說,高效的演算法固然效率高些,但即使演算法相同,簡潔代碼也不見得比複雜代碼效率高,現在時興空間換時間,應儘可能減少迴圈的使用,特別是少用多重迴圈,或者儘可能在一個迴圈中做更多的事。聊到最後,我在電腦上給他看如下兩段代碼:
size_t strlen1(const char *str)<br />{<br />const char *p = str;<br />while(*p) p ++;<br />return (size_t)(p - str);<br />}</p><p>size_t strlen2(const char *str)<br />{<br />unsigned v;<br />const char *p = str;<br />while(*p && ((unsigned)p & 3))<br />p ++;<br />if (*p == 0)<br />return (size_t)(p - str);<br />for (v = 0; !v; p += 4)<br />{<br />v = (*(unsigned*)p - 0x01010101) & 0x80808080;<br />if (v)<br />v &= ~*(unsigned*)p;<br />}<br />for (; (v & 0xff) == 0; p ++)<br />v >>= 8;<br />return (size_t)(p - str - 4);<br />}<br />
我說,這是C語言初學者最熟悉的計算字串長度函數,版本一是經典寫法,應該算是簡潔的了;版本二是我按BCB2007的strlen彙編函數改寫的,看起來相當複雜,你說那個版本效率更高些?
他琢磨了很大一會說,版本二構思相當巧妙,迴圈次數比版本一大大減少,但是迴圈中的運算量相對過大,而版本一的迴圈過程中幾乎沒有運算量,所以版本二的效率應該不會比版本一高多少。
我叫他將這兩段代碼抄回去測試一下,他卻直接在我的電腦上開始寫測試代碼,最後的測試結果讓他吃了一驚,版本二的平均運算速度居然比版本一高一倍以上。
他拿起筆和紙,將版本二抄了下來,說是回去後要好好研究一下......