首页/谭浩强在程序员圈子里的口碑如何?为什么?/
共2个回答0条评论

谭浩强在程序员圈子里的口碑如何?为什么?

wiki链接 谭浩强

程瀚
排序方式:被封时间
时间排序由新到旧
  • 1132 个点赞 👍

    查看全文>>

    EliAliOli
  • 47 个点赞 👍

    我觉得这个问题问得不够好。

    因为谭浩强是一个高校教材的编写者,同程序员群体交集很小,却与许多开设计算机专业的高校有很大的联系,而且在现在,谭浩强的教材不属于 C/C++ 语言学习的先决条件,有的人就算没接触过谭浩强的教材,也可以借助其他的方式达到学习的目的,从事相应的工作。

    所以,讨论谭浩强的“口碑”如何,意义不大。


    这个问题倒不如这样问:“为何有经验的程序员都不会推荐谭浩强的教材”。

    说老实话,我不会否认谭浩强对中国高等教育计算机专业的教学贡献,他的贡献集中在 20 世纪的 90 年代和 21 世纪的头十年,从 Fortran 到 Pascal 到 C/C++ 都有涉猎。那个时候我国才刚刚跨上“信息高速公路”有一段时间,而且电脑的普及率不如现在那么高,所以能够写出一本教科书是一件非常不容易的事情。

    但是,谭老的教材已经出到 2022 年了,最新版的教材,其作者名与上一版本没有变,依然是谭浩强,而且前言的落款名字是谭浩强,时间地点是“2022 年 1 月于清华园”。所以根本不是某些人想象的那样,谭老年事已高就对教材不管不顾了。

    还真就在一线,您气不气?

    可是,对于他现在编著的教材,我无法给他如同 20 年前一样非常正面的评价。

    就拿我说的这本最新版《C 程序设计教程(第 4 版)》(ISBN:9787302610250)[1]来讲吧,在本书的前言部分,谭老说明了此次修订版的特点是“按照 C99 标准进行介绍”。

    然而翻到正文第 8 页第 1.5 节,直接让我看破防了:

    在编好一个 C 语言源程序后,怎样上机运行呢?一般要经过以下几个步骤。
    (1)上机输入和编辑源程序。先进入 C 语言编译系统(一般是集成环境 IDE,如 Visual C++ 6.0)。建立一个文件,文件名自己指定,扩展名为 .c(如 rest.c 或 f.c)。通过键盘向此文件输入程序,并且认真检查有无错误,如发现有错误,要及时改正。这一工作称为“对源程序的编辑”。完成编辑后,将此源程序存放在自己指定的文件夹内(如果自己不专门指定,系统一般会自动把它存放在用户当前目录下)。

    发现问题了吗?

    且不说 IDE 的正确译法是“集成开发环境”,Visual C++ 6.0(下称 VC 6.0)根本不是支持 C99 标准的 IDE!

    这个致命的错误直接说明教材的修订是“换汤不换药”。

    那么有人要问了:“为什么 C99 标准的代码能在它上面编译成功?”

    答案是,C99 新增特性的代码在 VC 6.0 上根本不可能编译成功,但教材恰好介绍的是 C99 与往前标准之间的公共部分,当然没什么问题了。

    看 VC 6.0 的版本信息就知道为什么了:这个软件是 1998 年推出的,距今已有 24 年了,发布的时间正好在 C99 的标准之前,何况它对 C89 的标准也只是大部分支持的,就连微软都已经不在官网开放最后 Service Pack 6 的下载渠道了。

    另外,读者应该看到图中是用虚拟机呈现的,运行在 Windows XP 下(其实图里的是 Windows Server 2003,和 XP 是同一个内核)。

    事实上 VC 6.0 在 Vista 及以上的 Windows 系统根本就不能正常安装,想要正常安装是要大费一番周折的(包括安装程序开启兼容性模式、修改安装文件、在安装开始前勾掉一些组件);

    就算安装成功了,也有兼容性隐患,也就是在打开工程和编译代码的过程中会时不时出错,经常会出现因无法识别 Workspace 而整个工程报废的问题。

    由于 VC 6.0 是一个为 C++ 而设计的 IDE,因此很多学校的老师在教学中经常忽略了这样一个事实:它所创建的 Win32 Console Application 项目是一个 C++ 项目,而不是 C 项目。

    如果你用心看如下的提示,就知道它创建的代码文件的扩展名是 .cpp 而不是 .c,甚至如果创建空白项目,只有添加 .cpp 的源代码文件,就没给 .c 任何选项。

    虽然我知道有些人会杠,觉得就算这么做又不影响,只要能编译成功并运行就够了。

    但计算机科学是要讲究严谨的,C 与 C++ 根本就不是一回事,一匹披着羊皮的狼远比一匹真正的狼更可怕。尤其是如果还用它再学 C++ 的话,会很容易产生一种“C++ 包括了 C 的全部”、“先学 C 才能学 C++”的错误认识。

    事实上 C++ 之父早就对这一点解释过[2],这句话同时也侧面说明了 C 与 C++ 在设计上是有距离的:

    C is almost a subset of C++, but it is not the best subset to learn first because C lacks the notational support, the type safety, and the easier-to-use standard library offered by C++ to simplify simple tasks.
    (C 几乎是 C++ 的一个子集,但并不是首先学习的最佳子集,因为 C 缺乏符号支持、类型安全性和 C++ 提供的更易于使用的标准库来简化简单的任务。)

    然后就是 IDE 的使用:VC 6.0 相比许多现代的 IDE,没有智能补全的特性,只有非常有限而且观感很难看的语法高亮。

    如果出了错,也得要把构建信息的窗格调大,然后翻之前的文字才能看得清错误提示在哪里,不像某些 IDE 可以直接从错误中定位,告诉你错误在哪。

    这里我故意犯了个错误,但是编译失败的提示要拉大最下面的日志窗口才能看得方便

    对比一下其他的 IDE,高下立判。

    当然,你要问我 VC 6.0 的意义是什么,当然是怀旧了。因为可以保留给 B 站一些古董电脑的爱好者收藏,用来在老旧的计算机上编程。

    但是在大学课堂里,这种东西我实在看不出有什么进步的意义,甚至与现在广泛采用的 C11 标准过于脱节。

    所以,有这样一个问题:“为什么学习计算机 C 语言都建议使用 VC 6.0 呢?

    答案是这个问题的讨论前提根本就不成立。这样一个老掉牙而体验差的古董 IDE,怎么可能让学生学到真正的 C 语言呢?

    说起来谭浩强已经用了这么多年的 VC 6.0,直到现在还没有剔除,而且本书已经提及了它至少 13 页(实际的应该更多,因为是在 macOS 的“预览”里用系统内置的 OCR),可见谭老是打算把它用到入土了。

    不改这种“基本盘”也就算了,比起以往的教材,这次修订版倒是提了那么一点 Visual Studio 2010,算是一种进步,但在本书正文第 10 页看到了让我血压升高的内容:

    为了编译、连接和运行 C 程序,必须要有相应的编译系统。目前使用的大多是集成环境(IDE)的。Visual C++ 是使用较广泛的集成环境,它把程序的编辑、编译、连接和运行等操作全部集中在一个界面上进行,功能丰富,使用方便,直观易用。如果用 Windows 操作系统,可以用 Visual Studio 2010 来对 C 程序进行编译和运行。本书的配套教材《C 程序设计教程(第 4 版)学习铺导》介绍了怎样对 C 程序进行编辑、编译和运行。请读者参照它上机运行本章中介绍的 3 个 C 程序,初步掌握上机的方法。
    学会使用一种编译系统之后,在需要时学习和使用其他编译系统是不困难的。

    也就是说,为了知道怎么去使用 Visual Studio 2010,还得要再买一本配套用书(当然配套的书我没买,但阅读了若干页感觉很一般)。

    身为教材的编者,明明可以与时俱进地在教材里更新一下推荐的 IDE,却很鸡贼地放在了使用频率非常低的配套用书里,且不说有几个学生真的会为了一个教材的补充多花钱,这么做难道不是为师生徒增负担么……

    另外,在阅读这本书时,会发现谭老自造了一些无厘头的概念。

    比方说浮点型数(floating point number),谭老倒是提了正确的结论“浮点型数就是实数”,但往后的叙述里,却把浮点型数称为“实数”。

    这种说法当然是有问题的:因为从后往前推就不成立。

    谭老倒是让本书回避了高等数学的题目——

    由于许多学校把 C 语言的教学安排在一年级,而学生还未学完高等数学,因此本书不包括有关高等数学知识的例题。

    但是“实数”这个词,就算不是高等数学的重要概念,初等数学课堂里早就不知提了它多少遍了,很明显,实数的范围远比浮点型数据表示的数要大多了。

    对于无限位数的小数,如果在 C 语言中按浮点型数表示,存储的是一个近似的结果,不是对这个数真值的直接反映。所以,虽然我可以用sqrt()函数计算\sqrt{2} 的值约为 1.414214,但我绝对不能说 1.414214 = \sqrt{2},这是一个最基本的常识!

    更进一步,IEEE 754 标准规定了对于浮点型数的几种舍入处理方式,但无论是怎样形式的舍入,对于无限小数来说,可以在精度很高的情况下接近真值,但永远不会等于真值。

    (经过考证,Fortran 语言里倒是有“实数型”这一类型,其关键字为 REAL,其余的语言里没有,所以严重怀疑谭老是搞混了,或者直接拿教 Fortran 的思维方式教 C 语言)

    比方说宏定义(Macro Definition),谭老虽然提到了这个字眼,但在正文中一直没有废除“符号常量”的说法。

    殊不知宏定义的内涵远比“符号常量”的字面意思要多得多,“符号常量”这种说法没有很好地体现宏定义的“预处理”作用,而且也不会考虑到初学者会不会把它和常量这个概念混淆。我举个例子:

    #include <stdio.h>
    #define pow(x) x * x
    
    int main(int argc, char *argv[]) {
    	int num = 3;
    	printf("%d", pow(num));
    	return 0;
    }

    这个代码运行的结果是 9。显然pow(x)是宏定义,编译器在编译时,将pow() 替换为x * x的运算 ,将x替换为对应的值num,也就是 3。这种宏定义虽然有“符号”的意味,但不能称之为“常量”。

    还有,谭老把键盘上经常输入的半角双引号" 叫做“双撇号”。

    然而对照 Unicode 官网发布的 Unicode 15.0 代码表[3],真正符合“双撇号”意思的英文名称是“double prime”,符号为′′, 其 Unicode 编号为U+2033

    之所以“prime”有符号“撇”的意思,这里贴出韦氏词典(Merriam-Webster Dictionary)中的其中一个释义[4]

    the symbol ′ used to distinguish arbitrary characters (such as a and a′), to indicate a specific unit (such as feet or minutes of time or angular measure), or to indicate the derivative of a function (such as p′ or f′(x))

    此外韦氏词典还解释了什么是“double prime”[5]

    the symbol ″ used to distinguish arbitrary characters (such as a, a′, and a″), to indicate a specific unit (such as inches), or to indicate the second derivative of a function (such as p″ or f″(x))

    但是平常键盘上打的那个半角双引号,其 Unicode 编号是U+0022, 无论如何和“双撇号”完全不是一个东西,而且就算把“双撇号”复制进 IDE 里当引号使用,也会让编译器报错而不能通过。

    总之我是真不知道他到底是怎么想出来的这个名字……

    另外,本书虽然修订了一些错误(因此已经改正的错误在本回答中不再提及),特别是被许多人津津乐道的自增自减运算符,可喜的是这一版中,谭老不再强调它的重要性,而是以如下的话叙述:

    专业人员喜欢在使用 ++ 和 -- 运算符时,采取一些技巧,以体现程序的专业性,但使用 ++ 和 -- 运算符时,常常会出现一些人们想不到的副作用,最好只用最简单的形式,如 i++,i--,++i,--i,而且把它作为独立的表达式,不要把它作为一个表达式的组成部分。

    严格地说,“专业人员”是不会在自增自减运算符上采用“技巧”的,会使得代码的可读性降低,业务逻辑混乱,也不容易维护,而且谭老对“未定义行为”并没有一个科学的解释,没把“副作用”是什么展现出来(因为“未定义行为”这个问题与编译器的处理方式有关),但这个改变依然值得一些肯定。

    同样的,本书仍然有一些细节错误,而且有的是好几个版本都不改的。

    比如作者虽然说:

    在选择变量名和其他标识符时,应注意做到“见名知义”,即选有含义的英文单词(或其缩写)作标识符,如 count,day,month,class,total,country 等。

    然而全书看遍后,我只发现了极少数的例题做到了这一要求,大部分的变量名称都非常“简洁”,比如“a”、“b”、“c”、“i”。这种变量名在生产环境下是很不受欢迎的。

    又比如:

    经过编译所得到的二进制目标文件(扩展名为 .obj)还不能供计算机直接执行。前已说明:一个程序可能包含若干源程序文件,而编译是以源程序文件为对象的,一次编译只能得到与一个源程序文件相对应的目标文件(也称目标模块),它只是整个程序的一部分。必须把所有编译后得到的目标模块连接装配起来,再与函数库等系统资源相连接成一个整体,生成一个可供计算机执行的目标程序,称为可执行程序(executive program),其文件扩展名一般为 .exe,如 test.exe 或 f.exe 等。

    事实上这段话只呈现了 VC 6.0 编译器的编译过程,既然要本着与时俱进的原则,更应该介绍的是 gcc 编译器如何编译 C 程序。

    假如要编译一个文件叫做demo.c,这个文件被 gcc 编译器编译的时候,会经历如下四个阶段:

    ①预处理(pre-processing)阶段:对原有的 .c 代码包含头文件,进行宏定义的替换,并删去注释,如有条件代码,则做相应的准备,最后生成一个预处理文件 .i。以下为执行该阶段的命令:

    gcc -E demo.c -o demo.i

    ②编译(compiling)阶段:对代码进行词法分析和语法分析,在确认代码没有语法问题后,将其翻译成等价的中间代码表示或汇编代码。以下为执行该阶段的命令:

    gcc -S demo.i -o demo.s

    ③汇编(assembling)阶段:将编译阶段生成的 .s 文件转换成目标的机器语言代码。以下为执行该阶段的命令:

    gcc -c demo.s -o demo.o

    ④链接(linking)阶段:生成的目标机器语言代码不能直接执行,因为可能调用了某个库函数,或者使用了其他的变量或者函数。

    可执行文件中的函数调用有动态链接和静态链接两种。动态链接是让程序执行的过程中去寻找要链接的内容,文件较小,占用内存低;而静态链接会把库文件的代码全部加入到可执行文件中,文件较大,但静态链接库的执行速度较快。

    以下为执行该过程的命令,Windows 平台需要指定扩展名为 .exe,如果是静态链接,则命令最末尾要加上-static

    gcc demo.o -o demo

    至此,整个编译过程才算完整结束。

    而且,这段话还有一个问题,并不是所有的可执行文件都是 .exe,因为这里有个大前提:Windows 平台,.exe 的格式为 PE 格式。如果用过 macOS 和 Linux,就知道它们也有自己的可执行格式,分别为 Mach-O 和 ELF。

    正文第 115 页有个低级错误:

    程序分析:根据常识,偶数不是素数,所以只对奇数进行测试,在外层的 for 语句中,用 m = m + 2 使 m 每次增值 2。n 的作用是累计输出素数的个数,控制每行输出 10 个数据。

    “偶数不是素数”?数字 2 觉得很淦。

    关于浮点型数的介绍,正文第 42 页的这句话有点鬼扯了:

    C 编译系统把所有的浮点型常量都按双精度处理,分配 8 字节。这是为了使运算能得到较高的精度。

    无独有偶,正文第 46 页也有:

    即使是两个 float 型数据相加,也先都转换为 double 型,然后再相加

    首先既然是按 C99 标准介绍,那么就应该知道 C99 引入了浮点复数的类型,分为float complexdouble complexlong double complex,它们是定义在complex.h头文件里的。

    虽然浮点复数常量属于浮点型常量,但根本不会按双精度处理。而且 float 类型转为 double 类型运算这个规则,早在 C89 就已经被废止了,但是万恶的 VC 6.0 当然没有体现这一点。

    我寻思既然作者在正文第 41 页提到了 ANSI C,那么就应该知道 ANSI C 手册的这样一个规定:只有当操作数类型不同的时候,编译器会考虑朝着精度更高、长度更长的方向转换。[6]

    但事实上,两个同为float类型的数(当然都属于浮点型数)相加减乘除运算时,由于根本不存在格式转换,所以编译器不可能把它们转换为double类型!

    ……

    写得太累了,大概就整理到这里吧。当然,这本书存在的问题肯定不止这些,期待有高人能够继续补充。

    所以,回到开头,为什么有经验的程序员不会推荐谭浩强编著的教材来入门 C 语言,原因有如下几点:

    • 书中仍存在不严谨的漏洞
    • 通篇并未贯彻 C99 的标准,不利于新手对 C 语言形成一个完整的认识
    • 代码的风格较粗劣,与工作实际相脱节

    再回答一下这个问题:“为什么现在国内各大高校仍选用谭浩强的《C 程序设计》为教材?

    实际上好的学校早已不采用谭氏教材,虽然很多计算机专业或者计算机相关专业还是在用的,甚至有的与计算机不相关的专业(比如某些学校的机械专业)也在用。

    能用谭氏教材,很大一部分是为了任课老师的教学任务图方便,其次是为了保证作为中文教材的“权威”而不翻车——谭氏教材的特点是为应试教育服务的,所以对任课老师来说,这个教材的教案和课后习题答案是全网最好找的,考点清晰,出考卷也非常容易,不会在教学的时候讲崩。

    如果换成国外的教材当然也可以,但如果不是北大、清华那种顶尖的环境,可能会吃力不讨好,因为现在功利的学术环境,决定了对任课老师而言,只有躺平和过好自己的生活才是好的选择,那么这份矛盾,必然会无条件转移到学生身上来——课堂上学的云里雾里,课后得花时间去补。

    对大一的学生来说,读到这里可能会打破你对大学生活的美好幻想,可是这就是现实,而且越往后你越会发现这一点。

    但不管遇到什么样的老师,无论课堂上是否真的对你负责,该怎样应付平时成绩和考试是一方面,如何为自己的未来做准备更是一方面。这方面要坚持两点论与重点论的统一,课堂上的东西非常基础,如果学不好,可能会让成绩单不够光彩,对以后的深造是有影响的;另外,如果只把自己的一切押在课堂上,没有在课外掌握些什么,恐怕四年学出来也不会有什么好的结果。

    所以我的建议是,如果手上的教材不适合自己,那么就去看那些有用的参考书和网络资源(比如 B 站的网课),顺带锻炼自己的自学能力。毕竟现在的信息还是很发达的,还有搜索引擎方面不建议用某度,因为搜出来的很多都是广告,用必应可能会有更好的体验。

    另外,不要误会了,我说这些话不是来为偷懒找借口的——尽管我说了这么多教材本身有问题的地方,但你的学习能力不能因为教材而堕落。


    这个回答本来到此结束的,但我还想补充下,以免有些人曲解我的动机:

    中国高校的教材编排体系,相比国外落后是个不争的事实,这一点很多学者和博士研究生都体会过。

    我实在难以置信的是,某些人羡慕着像稚辉君那样的“天才少年”取得的过人成绩,感叹现在的大学教育相比社会的脱节之处,但一碰到给高校教材挑刺的言论却坐不住了,尤其是谭氏 C 语言教材,更是辩解说,“教材即使有错,他老人家没错”、“错的不是教材,是学校的教法问题”。

    可是,这样的言论在逻辑上就讲不通。本来学生在入学之前交了学费,其中就有教材费,那么一个教材要想更接地气,变得更完善,不接受批评是不行的。

    更何况谭浩强的教材都已经发展到了 2022 年,已经不再是那种本可以、本应该直接陈列在图书馆里的书,而是被许多高校采用的教材。

    最后摘录一下谭老在书的前言里的话:

    许多读者称赞我处处为读者着想,开创了计算机书籍贴近大众的新风,称我是计算机界的“平民作家” ,我很珍惜群众给我的这一称谓,这是对我的莫大鞭策。希望所有的教师和作者共同努力,把每一本书、每一门课程都做成精品,得到千万学生和读者的肯定和赞扬,这才是对我们的最高奖赏。

    熟悉我的都知道,我是个性子很直的人,天生不会拿权威的观点左右自己的想法。

    但我想说的是,挑战权威不是我的最终目的,求真务实才是。

    我只希望传达这样一个主旨思想:作为一个写教材的人,如果深知自己积累的口碑来之不易,那就应该在教材中为现在的学生作出表率,拿出自己应有的真诚。

    欲戴皇冠,必承其重。

    这是我今年的最后一篇回答,感谢阅读~

    冯柒柒
    38 次咨询
    4.8
    112638 次赞同
    去咨询

    参考

    1. ^谭浩强.C程序设计教程(第4版):高等院校计算机基础教育课程体系特色教材系列[M].北京:清华大学出版社,2022.
    2. ^Five Popular Myths about C++, Part 1 : Standard C++ https://isocpp.org/blog/2014/12/myths-1
    3. ^Components of Unicode 15.0.0 https://www.unicode.org/versions/components-15.0.0.html
    4. ^Prime Definition & Meaning - Merriam-Webster https://www.merriam-webster.com/dictionary/prime
    5. ^Double prime Definition & Meaning - Merriam-Webster https://www.merriam-webster.com/dictionary/double%20prime
    6. ^Linden, Peter van der. “Expert C Programming.” (1994).
    编辑于 2022-12-07 21:41・IP 属地江苏
    真诚赞赏,手留余香
    还没有人赞赏,快来当第一个赞赏的人吧!

    查看全文>>

    冯柒柒

1

  • 1
  • 跳至
Copyright © 2022 GreatFire.org