中文版:由于堆棧固有的增長和壓縮能力,以及嚴格和順序的命令用來壓入和彈出數據,堆棧已經成為管理順序變化數據(也就是函數調用的劇烈行為)的典型數據結構。 不知道各位看到上面這段翻譯是什么感受,我反正是一頭霧水。什么叫“順序變化數據?”什么叫“函數調用的劇烈行為?”看原文吧:The stack, due to its inherent ability to grow and shrink, as well as the rigid and predictable order in which data is pushed on and popped off,make it the ideal data structure for managing frequently changing data—namely, the turbulent behavior of function calls. 于是一切都清楚了,所謂的“順序變化數據”正確意思應該是“經常變化的數據”,再具體一點,指的是函數調用時,需要傳遞給堆棧的返回地址,參數,返回值等等,你也許還需要處理函數中的局部變量,所以數據是frequently changing 的。而不是什么“順序變化”!
如果上面這個例子讓你一頭霧水的話,下面這個例子就讓你覺得莫名其妙。這個例子是介紹堆棧的兩個基本操作PUSH和POP,我們先看英文版吧:Push accepts a single value and pushes it onto the stack. Pop accepts a single memory reference and pops the top stack value into it.這段話在中文版被翻譯成:壓入操作接收一個值并把它壓入堆棧。彈出操作會彈出堆棧頂部的值并把它賦給一個內存引用作為自己的返回值。 這時候容易讓人疑惑的是,翻譯最后的“作為自己的返回值”這句話是從哪來的?大家都該清楚Pop語句只是將棧頂元素賦值給那個接收的參數,并沒有什么返回值!。此外這種Push和Pop這種單詞,一般正規的默認不翻譯,保持英文更讓人容易理解。而返回值(return value)這個單詞在本章中特指函數的返回值,估計被人翻混了。
好了,上面兩個翻譯如果你說我強詞奪理的話,這次看的這個錯誤也許是個人都不能容忍了:英文原版:Call is a lot like Jmp in the sense that it causes the flow of execution to branch to another instruction.However, in addition to simply making an unconditional jump, it also pushes the current instruction index (which is its own index, as well as the return address) plus one onto the stack. It adds one to its own address to make sure the function returns to the following instruction, not itself;otherwise you’d have an infinite loop on your hands.,在中文版中被翻譯成:Call使得執行流分支到另外一個指令,從這個意義上來說很想Jmp。然而,除了做了一個簡單的非條件跳轉之外,同時還把當前指令的索引(是它自己的索引,也是返回地址)壓入堆棧。它把自己的地址壓入堆棧來確保函數返回到下一條指令,而不是自己,否則的話就造成了一個無窮循環。問題來了,英文原版紅色的plus one在中文版的翻譯中哪去了?英文原版的意思是當發生函數調用時,Call指令會把“當前指令的索引+1”做為函數返回值壓入堆棧,這樣函數退出時,就執行堆棧中的“當前指令的索引+1”的指令??煞g中卻把+1漏掉了,這不正是造成死循環的原因嗎?
其他的翻譯晦澀,翻譯錯誤還很多,比如書中后來提到了堆棧對返回地址(return address)的處理,以及堆棧對函數返回值(return value)的處理。對照英文原版可以看到,中文版至少有兩處把return value 和return address翻譯混淆,本該是“返回地址”的地方翻譯成了“返回值”。