吳均 《續齊諧記﹒ 陽羨書生》
陽羨許彥於綏安山行,遇一書生,年十七、八,臥路側,云腳痛,求寄鵝籠中。彥以為戲言。書生便入籠,籠亦不更廣,書生亦不更小,宛然與雙鵝並坐,鵝亦不驚。彥負籠而去,都不覺重。
前行息樹下,書生乃出籠謂彥曰:「欲為君薄設。」彥曰:「善。」乃口中吐出一銅奩子,奩子中具諸餚饌,珍羞方丈。其器皿皆銅物。氣味香旨,世所罕見。酒數行,謂彥曰:「向將一婦人自隨,今欲暫邀之。」彥曰:「善。」又於口中吐一女子,年可十五、六,衣服綺麗,容貌殊絕,共坐宴。俄而書生醉臥,此女謂彥曰:「雖與書生結妻,而實懷怨。向亦竊得一男子同行;書生既眠,暫喚之,君幸勿言。」彥曰:「善。」女子於中吐出一男子,年可二十三、四,亦穎悟可愛,乃與彥敘寒溫。書生臥欲覺,女子口吐一錦行障遮書生。書生乃留女子共臥。男子謂彥曰:「此女子雖有心,情亦不盡。向復竊得一女人同行,今欲暫見之,願君勿洩。」彥曰:「善。」男子又於口中吐一婦人,年可二十許。共酌,戲談甚久。聞書生動聲,男子曰:「二人眠已覺。」因取所吐女人還納口中。須臾,書生處女乃出謂彥曰:「書生欲起。」乃吞向男子,獨對彥坐。然後書生起,謂彥曰:「暫眠遂久,君獨坐,當悒悒邪?日又晚,當與君別。」遂吞其女子諸器皿悉納口中,留大銅盤可二尺廣,與彥別,曰:「無以藉君,與君相憶也。」
彥大元中為蘭臺令史,以盤餉侍中張散。散看其銘題,云是永平三年作。
註:「 大元」 疑為 「 太元」, 東晉孝武帝的年號 。「永平」 為 東漢明帝的年號 。
解析:
吐出 | 吐出 | 吐出 | ||||
書生 | -------> | 妻子 | -------> | 情夫 | -------> | 情婦 |
<------ | <------ | <------ | ||||
吞回 | 吞回 | 吞回 |
這麼多人出場和離去,沒有發生任何爭吵,也沒有破綻,靠的是什麼機制呢? 那就是資訊科技課談的「堆疊」(Stack),先進後出(First In Last Out)。妻子最先被吐出來,但最後被吞回去。
主程式呼叫副程式,要使用到堆疊。在呼叫副程式前,會先把下一條指令的位址 push 到堆疊 。當要返回時,會從堆疊 pop 出返回位址。
呼叫 | 呼叫 | 呼叫 | ||||
主程式 | -------> | 副程式1 | -------> | 副程式2 | -------> | 副程式3 |
<------ | <------ | <------ | ||||
返回 | 返回 | 返回 |
書生需要妻子時,才把她吐出來。不需要她時,就把她吞回去; 同樣,妻子需要情夫,才把情夫吐出來。不需要他時,就把他吞回去。如此比較不佔空間,因為 若書生沒睡覺,妻子也不敢把情夫吐出來。這就是動態連結函式庫(Dynamic Link Library,縮寫為DLL)的觀念。
所謂動態連結(DLL),就是把一些經常會共用的程式碼(靜態連結的OBJ程式庫)製作成DLL檔,當執行檔呼叫到DLL檔內的函式時,Windows作業系統才會把DLL檔載入記憶體內,DLL檔本身的結構就是可執行檔,當程式需求函式才進行連結。透過動態連結方式,記憶體浪費的情形將可大幅降低 。
當主程式呼叫副程式 1 時,才把副程式 1 動態連結載入到RAM。當不再需要副程式 1 時,又把它從RAM移除。如果是靜態連結,會把主程式和可能用到的副程式全部事先都載入到RAM。有可能在主程式執行過程中,因為條件沒成立,都不會去呼叫 某個副程式,這樣的副程式祇是空佔RAM的空間。
在南北朝(梁)那麼遙遠的年代,就已經有堆疊和DLL的觀念,真是神奇啊!