2022年C程序设计语言 .pdf
C 程序设计语言翻译挑错The C Programming Language的中译本C 程序设计语言由机械工业出版社出版,徐宝文、李志翻译,尤晋元审校,K&R 甚至为它专门写了个中文版序,可惜经典又被翻译糟蹋了。 我手头的是2008年 4 月第二版第19 次印刷,依然有着翻译错误甚至印刷错误(不可原谅! ) ,也许大名鼎鼎的尤晋元教授审校时忘记带眼镜了。有错误不可怕,但缺乏错机制就让人恼火了。遍寻网络也找不到官方勘误表,甚至交流方式都没有,只能说出版社和译者没把后续服务当回儿事。有些作译者通过个人主页、博客或邮件组同读者进行交流,在此表示敬佩。但整体而言,IT 图书的出版以图灵运做的最好,有和读者交流的专门网站 ,图书勘误也在上面发放,这样大大降低了双方交流的成本,必须夸奖!回到正题上来,我正在阅读K&R 的英文版(提高英语和C 语言水平),但信心不足,辅以中文版一册,发现许多错误,不爽,决定在这里记下来(果然IT 技术书籍有原版就不要读翻译本,唉),这篇blog会写很长时间,因为我的英语水平一般般(现在,只是现在一般般)。2012.07.23 阅读第一章, 发现一些小错误让人十分恼火,因为直接读中文就能看得出来。说实话一边读原版一边对比蹩脚的翻译实在太不爽了。接下来我打算采用先英文,后中文的方式看剩下的内容,那么只有那些大的错误(类似引言1)或者火星中国人才能读懂的句子才会发现。所以,为了自己好, 一定要学好英语呵! K&R 不适合初学者, 如果你头次接触C 语言,我推荐宋劲杉老师的 Linux C 编程一站式学习,或者你英语好就直接读英文的入门材料,比如Learn C The Hard Way这种;至于老手,看原版吧。我把其他人的错误总结记在后面,大家看一下。2012.07.27 引言1.pXIII第 5 段, “ 函数定义 可以不是 嵌套的, ”你妹啊,幸好我之前学过C,不然就被忽悠了!原文是 Function definitions may not be nested, may not在这里是 “ 不可以 ” 的意思啊老师!就算你英语不好,C 语言总该用过吧,这也太坑爹了!正确翻译: “ 函数定义不可以嵌套” 。2. pXIII第 10 段, “ 这就意味着必须通过调用函数来比较两个字符串吗”这句不算错误,只是作者在这里吐槽一下自己,很幽默的一句被翻译得索然无味,原文是:“ You mean I have to call a function to compare two character strings?”3. pXV第 2 段, “ 所采用的方式将比第1 章更加 形式化 一些 ”名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 4 页 - - - - - - - - - 原文是 formlly,这里用 ” 正式 “ 更易懂些:“ 所采用的方式将比第1 章更加 正式 一些 ”2012.07.23 第一章 导言1. p25,练习1-20 ,“ .使空格充满到下一个 制表符终止位的地方”原文 next应该翻译成 “ 靠着,紧挨 ” 的意思,不是下一个!“ .使空格充满到挨着 制表符终止位的地方”2012.08.22 - 第三章 控制流1. p54,3.7 节最后一段,“ 当循环的后面部分比较复杂 .则可能需要 把测试条件颠倒过来或者 缩进另一层循环,这样做会使程序的嵌套更深 。”这一整段我个人以为都错了。“ The continue statement is often used when the part of the loop that follows is complicated, so that reversing a test and indenting another level would nest the program too deeply.”当循环体很复杂,逆转测试条件下再缩进一层执行会让程序会嵌套得太深时,就需要continue语句出场表现了。结合上上面的例子看,如果不用continue,就要写成这个样子:for (i = 0; i = 0) . reversing a test 指 ai = 0 , indenting another level 指 for 内的循环体嵌入又嵌入到if 里去了。(这一句的术语我有敲不准,大家还是结合例子看原文吧)名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 4 页 - - - - - - - - - 2012.08.21 以下内容来自豆瓣网友jtuki :页码:第8 页 2011-01-30 22:34:47 引言部分(准确的说是XIII 页)一开始就出现了严重的翻译错误,比较窘。函数定义可以不是嵌套的- 翻译错误。原文是may not be nested 即函数定义不可以嵌套。但是,在GNU C 实现中,这个来自ANSI 的规则被打破,前者允许函数嵌套定义。页码:第42 页 2011-01-30 22:37:42 条件表达式expr1 ? expr2 : expr3 本质上就是一个表达式,其类型根据expr2 和 expr3 的类型决定(此处书上说成是expr1 和 expr3 属于翻译错误)。如果expr2 和 expr3 类型不同,则根据转换规则来决定,与expr1 求值结果无关。页码:第60 页 2011-01-30 22:38:34 对于atof 的描述说它占用了过多的空间是翻译错误,原话是that would take more space than we care to use,即更高质量的input conversion 需要更多的space 才行。页码:第76 页 2011-01-30 22:38:57 严格地说,这些内容没必要单独存放在文件中翻译错误,原文Strictly speaking, these need not be files; the details of how headers are accessed are implementation dependent。正确翻译严格来讲,这些头文件不一定非要是文件,具体如何访问这些头文件,同具体实现有关。页码:第89 页 2011-01-30 22:39:21 我们在这里使用size_t 作为函数strlen 返回值类型翻译错误,正确翻译应该是如果我们够cautious ,那么我们就会采用size_t 做为我们的返回值类型。size_t 其实就是unsigned int 或者unsigned long 了(具体是implementation defined 即由实现定义)。与 NULL 一样都是定义在stddef.h 文件中。页码:第91 页 2011-01-30 22:39:59 对于如下的拷贝字符串操作。void strcpy(char *s, char *t) while (*s+ = *t+) ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 4 页 - - - - - - - - - 书上给出的描述翻译有点问题。原文- Although this may seem cryptic at first sight, the notational convenience is considerable, and the idiom should be mastered, because you will see it frequently in C programs.即,这种写法初看起来写的很隐晦,然而其所带来的便利是可观的,我们应该掌握这种写法,因为这种写法已经成了一种惯例,在C 语言程序中,我们会经常碰到这样的写法。另外,注意unary 操作符* 和 + 以及- 是从右往左的结合性。页码:第121 页 2011-01-30 22:40:33 虽然这可以不用通过在线性数组中 . 时间过长这句话翻译错误。去掉虽然和但即可。页码:第124 页 2011-01-30 22:40:56 在结束该例子之前 . 第二 . 不同类型指针的问题?这一段翻译很混乱!而且第二句话的意思还翻译错了。原文,以及jtuki 版本的翻译,如下。+_+ Before leaving this example, it is also worth a brief digression on a problem related to storage allocators. 结束这个例子之前,请允许我稍微跑个题,讲一讲存储分配器(storage allocator)的问题。jtuki 注释:所谓存储分配器,就是给程序中某些对象分配存储空间的东西。Clearly it desirable that there be only one storage allocator in a program, even though it allocates different kinds of objects. But if one allocator is to process requests for, say, pointers to chars and pointers to struct tnodes, two questions arise. 很显然,我们希望一个程序中,仅仅有一个存储分配器(jtuki 注释:毕竟少量的接口会更加简洁和清晰),尽管在一个程序中,我们需要为很多不同类型的对象分配存储空间。如果一个分配器既要为,比如说,char 型指针,以及结构体型指针,分配存储空间,那么就会存在如下两个问题。First, how does it meet the requirement of most real machines that objects of certain types must satisfy alignment restrictions (for example, integers often must be located at even addresses)? 第一,它怎么满足大部分机器对于object 的对齐( alignment)限制(比如,整型通常必须被分配在偶数开头的地址序列上)?Second, what declarations can cope with the fact that an allocator must necessarily return different kinds of pointers? 第二,我们采取什么样的声明方式,才能够让分配器返回不同类型的指针?翻译结束。我似乎翻译的也不太好。离信达雅的标准估计还很远。=_= 讲完这两点后,作者就很自然的引出了标准库malloc 函数和void * 型指针。 一般尽管void * 型指针可以自动类型转换,变成任意具体对象的指针,但是一般我们习惯强制转换。- 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 4 页 - - - - - - - - -