谭浩强《C程序设计》(第四版)错误不完全汇集

2023年4月27日12:09:43

前言
p12
① 数据类型介绍中,增加了C99扩充的双长整型(long long int)、复数浮点型(float complex,double complex ,long long complex)、布尔型(bool)等,使读者有所了解。
② C99要求,main函数的类型一律指定为int型,并在函数的末尾加一个返回语句“return 0;”。

评:long long complex,bool根本是子虚乌有的。数据类型都整不明白,还谈什么语言、算法呢?
C99并没有要求main函数的类型一律指定为int型
main函数的类型一律指定为int型其实是C89要求的

p16
“位运算”是C语言区别于其他高级语言的一个重要特点。

不顾常识,胡说八道

第一章 程序设计和C语言
1.2 什么是计算机语言
p1
计算机发展的初期,一般计算机的指令长度为16,

不晓得老谭把什么时代算做“计算机发展的初期”

p2
符号语言……LD代表“传送”等————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p2
LD一般表示赋值
p2
高级语言……用到的语句和指令是用英文单词表示的————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p2
高级语言这个层次没有指令这个概念

p3
C(系统描述语言)————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p3

这是把张飞当张良了

p3
C++(支持面向对象程序设计的大型语言)————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p3

C++是一种支持多重编程范式的通用程序设计语言

1.3 C语言的发展及其特点
p4
……增加了一些功能,尤其是C++中的一些功能,命名为ISO/IEC 9899:1999。

又在信口开河

p4
1983年,美国国家标准协会(ANSI)成立了一个委员会,根据C语言问世以来各种版本对C语言的发展和扩充,制定了第一个C语言标准草案(‘83 ANSI C)

曾经的子虚乌有的“87 ANSI C”不见了,很好。但这个‘83 ANSI C是哪来的呢?

p4
1990年,国际标准化组织ISO(International Standard Orgnization)接受C89……
评:ISO啥时候改名了?
我记得这个组织的正式名称是International Organization for Standardization
难怪书这么“水”
ISO都被山寨了

p5
C语言的运算符包含的范围很广泛,共有34种运算符(见附录C)。

评:这个恐怕要麻烦老谭自己去亲自数数了。34种究竟是怎么数出来的呢?再说附录C也不是关于运算符的啊

p5
C语言把括号、赋值和强制类型转换等都作为运算符处理,从而使C语言的运算类型极其丰富,表达式类型多样化。

评:怎么就“从而使”了呢?哪来的这种因果关系?
“运算类型极其丰富”应该是“运算种类极其丰富”
“表达式类型多样化”,不知所云

p5
C语言是完全模块化和结构化的语言。

评:什么叫“完全模块化”?什么叫完全结构化?这两个概念的定义是什么?
p5
例如,整型量与字符型数据以及逻辑型数据可以通用。

评:这是对初学者很严重的误导。另外“量”与“数据”并列,从小学生作文的角度也是说不过去的

p5
C语言……是成功的系统描述语言……

评:请问是描述什么“系统”?如何“描述”?知不知道什么叫“系统描述语言”

p5
而且C编译系统在新的系统上运行时,可以直接编译“标准链接库”中的大部分功能,不需要修改源代码,因为标准链接库是用可移植的C语言写的。

评:C编译系统在新的系统上运行:估计老谭在linux下成功地运行了他的VC6
可移植的C语言:说实话,没见过这种C语言
可以直接编译“标准链接库”中的大部分功能:看不懂这是说什么哪

1.4 最简单的C语言程序
p6
int main()

这是一种过时的写法,不符合C99的精神。C99只是为了兼容现有代码才允许这种写法
p6
而返回程序窗口

实际上恰恰是关闭程序窗口,返回IDE界面

p6
C99建议把main函数指定为int型(整型)

其实是C89标准的规定,老谭大概是为以前不规范的void main找台阶
p6
在main函数中,在执行的最后设置一个“return 0;”语句。当主函数正常结束时,得到的函数值为0,当执行main函数过程中出现异常或错误时,函数值为一个非0的整数。

评:写了“return 0;”居然还可能得到“一个非0的整数”?太神奇了吧

p7
文件后缀.h的意思是头文件(head file),因为这些文件都是放在程序各文件模块开头的。

评:head未必是以文件形式存在。
文件放在“文件模块开头”是莫名其妙的说法
p7
则表示从到本行结束是“注释”。

语文问题

p8
printf(“sum is %d\n”, sum);
……在执行printf函数时,将sum变量的值(以十进制整数表示)取代双撇号中的%d。

执行printf函数:怎么读怎么别扭,应该是调用printf函数
将sum变量的值(以十进制整数表示)取代双撇号中的%d:变量的值是取代不了%d的
p9
第2行输出“大数为8”。

输出的是“max=8”
p9
程序第4行是……

那是第5行

p9
执行scanf函数,从键盘读入两个整数,送到变量a和b的地址处,然后把这两个整数分别赋给变量a和变量b。

哪来的什么“然后”?

p10
%d由变量c的值取代之。

不是由“变量c的值”取代之

p10
例如可以把例1.2程序中的“int a,b,sum”放到main函数前面,这就是全局声明,在函数外面声明的变量称为全局变量

这是教唆,多数情况下是很糟糕的写法。
此外C没有全局变量这种说法,只有外部变量

p10
源积程序……

p11
①函数首部……包括函数名、函数类型、函数属性、函数参数(形式参数)名、参数类型。

“函数类型”:错误使用术语
“函数属性”:莫名其妙的说法

p11
函数体一般包括以下两部分。
 声明部分
 执行部分

作为一本号称“按照C99标准”的教科书来说,这种说法显然是错误的
p12
在每个数据声明和语句的最后必须有一个分号。分号是C语言的必要组成部分。

武断+无知
此外“数据声明”也很荒唐,C语言没有这样的概念

p10~12
“1.4.2 C语言程序的结构”这一小节下面的小标题是

1.4.2 C语言程序的结构
(1) 一个程序由一个或多个源程序文件组成。
(2) 函数是C语言的主要组成部分。
(3) 一个函数包括两个部分
(4) 程序总是从main函数开始执行的
(5) 程序中对计算机的操作是由函数中的C语句完成的。
(6) 在每个数据声明和语句的最后必须有一个分号。
(7) C语言本身不提供输入输出语句。
( 8 ) 程序应当包括注释。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p10~12
仔细回味一下,很有喜感。
即使当作小学生作文,恐怕也不合格吧
讲C语言的程序结构,怎么冒出来“C语言本身不提供输入输出语句”了呢?
程序结构和“程序总是从main函数开始执行的”又有什么关系呢
说老谭离题万里、云山雾罩不冤枉他吧

1.5 运行C程序的步骤与方法
p12
1.5 运行C程序的步骤与方法
这一小节讲的实际上是用C语言开发程序的过程与步骤(编辑、编译、链接及运行)
从内容上看,标题文不对题

这一小节的重大疏失是
只讲了编译和运行时发现错误应该返回修改源程序
但对链接时可能也会发生错误却只字未提
事实上链接错误也是编程最常见的错误之一
对这样常见的一大类错误怎么可以忽视呢

语言罗嗦和概念不清的毛病在这一小节同样存在
譬如

(1)上机输入和编辑源程序。通过键盘向计算机输入程序,……————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p12
什么叫“通过键盘向计算机输入程序”?难道这不属于“编辑”的范畴吗?
试问老谭,“输入“和”编辑”之间的区分到底应该如何界定?

p13
经过编译得到目标程序文件f.obj,再将所有目标模块输入计算机————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p13

“将所有目标模块输入计算机”:老谭能否演示一下怎么输入?
p14
集成环境(IDE)————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p13

直接无视D字的含义

1.6 程序设计的任务
p14
1.6 程序设计的任务————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p14
这是第一章最糟糕的一个小节
首先是文不对题
程序设计的任务只能是解决问题,不可能是别的什么
但这一小节的内容其实是对完整的程序设计过程和步骤的描述
如果仅仅如此
问题并不严重
可是书中对完整的程序设计过程和步骤的描述居然是

从确定问题到最后完成任务,一般经历以下几个工作阶段:
(1)问题分析。……
(2)设计算法。……
(3)编写程序。……
(4)对源程序进行编辑、编译和连接。……
(5)运行程序,分析结果。……
(6)编写文档。……
这种“谭式”工作流程几乎是置几十年来人类程序设计的经验和思考于不顾,全然自创的
不过说实话,我倒更希望老谭的这一小节能找本象样的书抄一抄,因为那样至少不会荒谬的如此离谱

首先,轻飘飘的一句“从确定问题到最后完成任务”
把确定问题当成了轻而易举的一件事
事实上除了判断一个正整数是否是素数这样的问题
“确定问题”的难度常常并不亚于解决问题

其次,老谭的“问题分析”居然是

对于接手的任务要进行认真的分析,研究所给定的条件,分析最后应该到达的目标,找出解决问题的规律,选择解题的方法。在此过程中可以忽律一些次要的因素,使问题抽象化,例如用数学式子表示问题的内在特性。这就是建立模型。
我的印象,这不过是中学数学解题方法与数据建模方法的一种杂交而已,不伦不类四不象。
“对于接手的任务要进行认真的分析,研究所给定的条件”:空对空的废话
“分析最后应该到达的目标”,目标都不明就编程?
“找出解决问题的规律,选择解题的方法”,耳熟,很有亲切感。后来想起来中学数学老师总这么说
“在此过程中可以忽律一些次要的因素”:从胆量方面来说不得不赞一个。复杂的东西咱都推还给客户好了
“使问题抽象化”:不知所云
“用数学式子表示问题的内在特性”,软件设计解决的问题有几个有数学式子?
“这就是建立模型”:不打自招

第三,“设计算法”中只字未提数据结构。老谭是强调“算法—程序的灵魂”的,可惜他一点不懂什么叫数据结构
在老谭的影响和带动下,经常看到一群整天把算法挂在嘴边但却连最基本的数据类型都搞不懂的家伙,根本就不能指望他们能懂得数据结构

第四,(3)的“编写程序”和(4)的“对源程序进行编辑”到底有什么分别

第五,(6)编写文档。程序开发完了,终于想起来“文档”了。任何一个软件工程专业的二年级本科生都能指出为什么这很荒谬。更荒谬的是,在老谭那里,“文档”居然不过是“程序说明书”、“帮助(help)”或“readme”。

习题
p15

这一章的习题也很糟糕

习题
6.编写一个C程序,输入a,b,c三个值,输出其中最大者。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p15

这道题不具备程序设计习题的最基本要求,是错误的题目。没有人可以做出这种题目。这反映了作者对软件开发基本上一窍不通

第二章 算法——程序的灵魂
p16
第二章 算法——程序的灵魂
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p16

这一章总的来说就如同阑尾,而且是发炎的阑尾。
p16

首先映入眼帘让人感到眼前一亮的是
著名计算机科学家沃思(Nikiklause Wirth)……
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p16

又来了。有人做过实验,google Nikiklause Wirth搜来的全是中文网页。不要问我为什么,只有智商约等于0的人才会问这样的问题。
由此可见,垃圾也是会疯狂地繁殖的。有人总喜欢沾沾自喜地拿“1100万”说事儿, 我倒想问一句,“1100万”个错误是个什么概念,“1100万”堆垃圾又会造成多大的污染。

p16
对于 Wirth 提出的
算法+数据结构=程序
老谭评论道:

直到今天,这个公式对于过程化程序来说依然是适用的。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p16
没有任何理由和依据,而敢于指责大师的公式具有局限性,不能不承认谭大师很有“勇气”。
接着,老谭提出

实际上,一个过程化的程序除了以上两个主要因素之外,还应当采用结构化程序设计方法进行程序设计,并且用某一种计算机语言表示。因此,算法、数据结构、程序设计方法和语言工具4个方面是一个程序设计人员所应具备的知识,在设计一个程序时要综合运用这几方面的知识。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p16
感慨:大师总是一针见骨地道出事物的本质;“伪大师”总是点金成铁狗尾续貂并且把水搅混。不妨再续狗尾:小学数学也是“程序设计人员所应具备的知识”。
2.1 什么是算法
p16~17
2.1 什么是算法————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p16

本小节前半部分介绍什么是算法,后半部分讨论了数值算法与非数值算法。主要毛病在后半部分。
后半部分实际上毫无必要;数值运算算法和非数值运算算法属于作者闭门造车自创的不规范用语(估计是不怎么读文献所导致);
对各种数值运算都有比较成熟的算法可供使用————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p17
乃极其武断的信口开河,表明作者对数值计算领域惊人的无知。

2.2 简单的算法举例
p17
2.2 简单的算法举例
这一小节读起来犹如嚼棉花的感觉,只好快些扫过。
p18
例 2.1
…由于计算机是高速运算的自动机器,实现循环是轻而易举的……
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p18

脑残是怎样炼成的,这种似是而非的“由于”句型功不可没。“循环”居然是由于“高速”,咄咄怪事。

p19~20
例 2.2
…从图2.1可以看出:“其他”这一部分,包括不能被4整除的年份,以及能被4整除,又能被100整除,但不能被400整除的那些年份(如1900年),它们都是非闰年。
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p19

敢问大师有没有亲自看过图2.1中“其他”这部分写的究竟是什么?要是看过的话,我们可就知道什么叫睁着眼睛胡说了
p20
例 2.4
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p20
其中描述的算法必然导致拖泥带水的代码。
p21
例 2.5……
所谓素数(prime),是指除了1和该数本身之外,不能被其他任何整数整除的数
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p21

厉害!把素数的定义都给改了,数学家们该感到汗颜了吧。
另外作者连“整数”和“正整数”的区别都搞不清楚
p21
判断一个数n(n≥3)是否为素数……
实际上,n不必被2n-1的整数除,只须被2n/2间的整数除即可,甚至只须被2~n之间的整数除既可。例如,判断13是否为素数,只须将13被2,3除即可,如都除不尽,n必为素数。
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p21

2~n/2 , 2~n 这两个区间到底哪个大?怎么后者竟然成了“甚至” 了呢
2.3 算法的特性
p21
2.3 算法的特性
……
(2)确定性。算法中的每一个步骤都应当是确定的,而不不应当是含糊的、模棱两可的。…… 也就是说,算法的含义应当是唯一的,而不应当产生“歧义性”。所谓“歧义性”,是指可以被理解为两种(或多种)的可能含义。 ————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p21
用老谭自己的矛攻一下他自己的盾
前一章的一道习题

6.编写一个C程序,输入a,b,c三个值,输出其中最大者。
这个题目本身是否“含糊”,是否具有“歧义性”?
问题本身就“模棱两可”,又何谈算法的“确定性”呢?

2.4 怎样表示一个算法
p22
2.4 怎样表示一个算法
流程图是用一些图框来表示各种操作。用图形表示算法,直观形象,易于理解。美国国家标准化委员会 ANSI(American National Standard Institute)规定了一些常用的流程图符号(见图2.3),已为世界各国程序工作者普遍采用。 ————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p22
首先ANSI是 American National Standards Institute.
其次,老谭把ANSI搬出来是无知的卖弄。理由是:
这个标准有ISO版本,ANSI采纳了这个ISO标准。而且对应于ISO标准,我国有自己的GB。这些标准的内容是一致的。老谭不谈GB,不谈ISO,却舍近求远地扯什么ANSI标准,又有什么特殊的理由呢?只能说他自己并不熟悉这些标准及其相互的关系。
而且书中的流程图根本不符合无论是 ISO标准还是GB还是ANSI标准,流线乱窜,甚至全书中压根就没有标准用来表示循环的基本图形。
既然连这些标准读都没读过,把ANSI搬出来不是唬人又能是什么呢?

p26
2.4.3 三种基本结构和改进的流程图
1.传统流程图的弊端————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p26
成功地把滥用goto的危害移花接木地指误为传统流程图的弊端。

……人们规定出几种基本结构,然后由这些基本结构按一定规律组成一个算法结构(如同用一些基本预制件来搭成房屋一样),如果能做到这一点,算法的质量就能得到保证和提高。
说的象真的似的。C语言再好也没耽误老谭写出那么多垃圾代码呀。由“基本结构”“按一定规律”就一定能保证算法的质量?!

p26
2.三种基本结构
1966年,Bohra和Jacopini提出了以下3种基本结构,用这3种基本结构作为表示一个良好算法的基本单元。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p26
首先把Böhm的名字错误地写成了Bohra。
其次更严重的是Böhm和Jacopini根本就没有提出什么3种基本结构,更没有提出“用这3种基本结构作为表示一个良好算法的基本单元”。3种基本结构在之前的高级语言中普遍存在。
Böhm和Jacopini仅仅不很严格地证实了向前的goto语句可以用其他语句实现,他们的论文发表的时候,Dijkstra反对goto语句的论文(1968)还没发表呢

p28
2.4.4用N-S流程图表示算法————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p28
N-S图废除了流线,哪里还是什么“流程图”?
事实上通用的说法是Nassi–Shneiderman diagram (NSD)
老谭的一个毛病就是喜欢发明一些狗屁不通的新概念
比如二级指针,行指针,数值运算算法
这些都是他自己根本没学懂的表现

p29
例2.15 ……
图2.31————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p29

图2.31的算法其蠢无比
明明一次循环就可以解决非要用两次循环
明明一个变量就可以解决非要用一个数组
而且那个50基本没有用处
因为可以轻易写出人数为一正整数时的算法

三鹿往奶粉里掺加大量三聚氰胺使婴儿身体受到摧残而被判刑
老谭往教科书里掺加的无知、错误和愚蠢使初学者大脑变残为什么不被判刑?
我看刑法应该参照食品卫生法考虑一下这个问题
在教科书中传播愚蠢败坏民族的智力难道不是犯罪?

p31
2.4.5 用伪代码表示算法————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p31
两道例题都是用for循环可以很漂亮完成
却莫名其妙的选择了用罗嗦的while循环描述
误导初学者

p32
2.4.6 用计算机语言表示算法
……用计算机语言表示的算法是计算机能够执行的算法。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p32
胡扯,计算机能够执行只有机器语言

p33
例2.19……
double deno=2.0,sum,term;
while(deno<=100)
{
……
deno=deno+1;
}————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p33
明显的错误,缺乏最基本的编程素质

2.5 结构化程序设计方法
p34
2.5 结构化程序设计方法
……关键是算法,有了正确的算法,用任何语言进行编码都不是什么困难的事情。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p34
这种对算法的片面强调是对初学者绝对的误导。误导的结果是,许多初学者往往只会用最拙劣数据结构绞尽脑汁地苦思复杂无比的“算法”。
此外,有经验的人都知道,即使懂得了算法,学习用另一种语言编程往往也不是那么容易的事,比如C++。

第三章最简单的C程序设计——顺序程序设计
P37

对第3章的点评

第3章 最简单的C程序设计——顺序程序设计
开场白讲了两件事:作者对如何学习编程的看法,介绍该书的做法。与该章的主题没什么关系。前者在第二章已经说过,后者应该是前言或第一章的内容,写在这里有没话找话自吹自擂之嫌。
作者对如何学习编程的看法基本是片面、偏颇及错误的,是对Wirth“算法+数据结构=程序”的曲解和错误发挥。这对学习者是一种根本上的误导。

3.1 顺序程序设计举例
两个例子从问题的提法到最后的代码都糟糕透顶、漏洞百出。这两个例题给学习者带来的负面影响有很多。从这两个例题中学习者不可能领悟到究竟什么是顺序程序设计,更不可能领悟到究竟什么是程序设计。他们很可能误以为编程就是把代数式写成表达式 + 进行函数调用。
更严重的是,谭书居然告诉读者“警告”可以作为正常来接受,这是教唆式的误导。
关于例3.1
例3.1 有人用温度计测量出用华氏法表示的温度(如69°F),今要求把它转换为以摄氏法表示的温度(如20°C)。

这个题目看似描述的平易近人通俗易懂。但我想小学语文老师会评价说,温度就是温度,和“有人”或没人、用或不“用温度计测量”有什么关系?“有人用温度计测量出”完全是废话。而小学数学老师会说,谭同学,69°F根本不是20°C。
这就是老谭。有人说他的书通俗易懂,其实多半只是似是而非且毫无内容的废话甚至病句而已。如果阅读不仔细很容易被他的似是而非唬过去,但只要稍微一推敲,立刻就能把他戳出几个洞。赞赏他的书的人,通常小学数学和小学语文都不咋样
此外,在题解中有这样一些毛病:
把算法说成是找公式
流程图写输入,但代码中是赋值运算
代码使用不合适的数据类型
容易出错的代码风格
……

3.2 数据的表现形式及其运算
这部分总的来说就是概念不清,逻辑混乱。
3.2.1 常量和变量
1.常量
“常用的常量有以下几类:(1)整型常量……(2)实型常量……(3)字符常量……(4)字符串常量……(5)符号常量”
2.变量
3.常变量
4.标识符
从这个标题结构很容易发现其荒谬,总体来说就是不伦不类:
把标识符和常量、变量并列;把“常变量”和“变量”并列;
对常量的分类同样是不伦不类
先介绍“符号常量”后介绍“标识符”是本末倒置

此外还有如下错误
3.2.1 之 1.常量 部分
“整型常量。如1000,12345,0,-345等都是整型常量。”,这里把“-345”这个常量表达式说成了常量
刚说完“十进制小数形式,由数字和小数点组成”,立刻给出了“-56.79”这个例子,明显自相矛盾。试问,“-”是数字还是小数点?
对字符常量和符号常量的讲解均存在错误。

3.2.1 之 2.变量 部分
对编程最重要的概念之一——变量的介绍存在惊人的致命错误(“变量名实际上是以一个名字代表的一个存储地址”)
“C99允许在函数中的复合语句(用一句花括号括起来)中定义变量。”属于用C89的知识冒充C99

3.2.1 之 3.常变量 部分
把const 变量想当然地说成是C99的,实际上C89就有const 这个关键字

3.2.1 之 4.标识符 部分
介绍的是过时(对于C99来说)的说法
P37
第3章 最简单的C程序设计——顺序程序设计
……
为了能编写出C语言程序,必须具备以下的知识和能力:
(1) 要有正确的解题思路,即学会设计算法,否则无从下手。
(2) 掌握C语言的语法,知道怎样使用C语言所提供的功能编写出一个完整的、正确的程序。也就是在设计好算法之后,能用C语言正确表示此算法。
(3) 在写算法和编写程序时,要采用结构化程序设计方法,编写出结构化的程序。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p37
这段总的、指导性的叙述,由于并不全面,具有本质性的缺失,因而是对初学者不折不扣的误导。
事实上仅有这些是不够的,当初学者仅仅注意这几点的时候是绝对不可能学好程序设计的。
众所周知,程序由数据、运算、控制和传输这四个基本成分。谭的叙述中完全看不到“数据”这个最基本成分的影子,这就造成了这样一种现象,许多学习谭书的人往往津津乐道地把“算法才是王道”挂在嘴边,但却对数据缺乏起码的必要了解。谭书本身最致命的一个根本缺陷就是对数据缺乏重视,不甚了了甚至存在大量的根本性的错误。
此外不难发现,谭的这段叙述和Wirth所说的“算法+数据结构=程序”在精神上是背道而驰的。

3.1 顺序程序设计举例
P37
3.1 顺序程序设计举例
例3.1 有人用温度计测量出用华氏法表示的温度(如69°F),今要求把它转换为以摄氏法表示的温度(如20°C)。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p37
这个题目看似描述的平易近人通俗易懂。但我想小学语文老师会评价说,温度就是温度,和“有人”或没人、用或不“用温度计测量”有什么关系?“有人用温度计测量出”完全是废话。而小学数学老师会说,谭同学,69°F根本不是20°C。
这就是老谭。有人说他的书通俗易懂,其实多半只是似是而非且毫无内容的废话甚至病句而已。如果阅读不仔细很容易被他的似是而非唬过去,但只要稍微一推敲,立刻就能把他戳出几个洞。赞赏他的书的人,通常小学数学和小学语文都不咋样。
P37~38
例3.1的讲解存在这样几个问题
1.

解题思路:这个问题的算法很简单,关键在于找到二者间的转换公式……
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p37~38
找个简单的公式也是算法?
2.

图3.1(N-S图)中
输入f的值
但代码中却是

f = 64.0;
这是“输入”吗
3.
代码中出现了从来没介绍过的关键字float
4.
代码中计算摄氏温度的语句是

c=(5.0/9)*(f-32);
这个风格怪异不说
初学者不可能明白为什么原来公式中的5写成了5.,而原公式中的9和32却没变
5.
老谭最后说

读者应能看懂这个简单的程序。
我看读者根本看不懂
P38

例 3.2 计算存款利息。有1000元,想存一年。有3种方法可选:(1)活期,年利率为r1;(2)一年定期,年利率为r2;(3)村两次半年定期,年利率为r3。请分别计算出一年后按三种方法所得到的本息和。

这也叫例题?谁知道你r1,r2,r3是神马东西啊
谁能做出来?我出1000元悬赏!
在公司里搞出这样的需求分析老板不抽他才怪

1000明明是问题中的常量
却非要设个变量(float p0=1000,)
难道不是脱裤子放屁吗?
既丑陋无比又容易弄出差错
这难道不是教小朋友们学坏吗
P38

例 3.2————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p38
再次出现了“N-S流程图”这个词
在书中一会儿“N-S流程图”,一会儿“N-S图”
明显的缺乏概念的统一
是形式逻辑中所说的“概念不清”的一种
N-S图中写的是“输入p0,r1,r2,r3的值”
代码中却是赋初值“float p0=1000,r1=0.0036,r2=0.0225,r3=0.0198,p1,p2,p3;”
P38

更可笑的是

运行结果:
p1=1003.599976
p2=1022.500000
p3=1019.898010
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p38

竟然给出了小数点后面的第6位
银行会按这个给你付钱吗?
不懂银行的业务写出这种代码只能是一个笑柄
更惊人的是
1000元按照年利率0.0036计
小学生用心算都能脱口而出本息是1003.6元
而你这个程序给出的结果竟然是1003.599976
这不是糟蹋C语言是什么
所以读老谭的书会变傻
这是确凿无疑的
P38

程序分析:第4行,在定义实型变量p0,p1,p2,p3,r1,r2,r3的同时,对变量p0,r1,r2,r3赋予初值。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p38
啥叫“实型变量”啊?
再说,在N-S图里不是“输入p0,r1,r2,r3的值”吗?
怎么到这里又成了“赋予初值”了呢?
P38

第8行,在输出p1,p2,p3的值之后,用\n使输出换行。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p38
这段文字出现在第38页
到这里为止,代码中的\n至少出现过20次左右
老谭已经讲过十几次\n是换行了
车轱辘话来回说是老谭的主要作文技巧
P37~39
#include <stdio.h>
int main()
{
float f,c;
f=64.0;
c=(5.0/9)*(f-32);
printf(“f=%f\nc=%f\n”,f,c);
return 0;
}
在使用Visual C++6.0编译系统时,……,会显示出“警告”信息:“在初始化时把一个双精度常量赋给一个float型变量”。

评:这条警告信息是捏造的,在这段代码中根本不存在“初始化”
P39

注意:……这是因为有的C编译系统(如Visual C++)把所有的实数都作为双精度处理。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p39
毫无根据的臆断,信口开河
P39
对这类“警告”,用户知道是怎么回事就可以了。承认此现实,让程序继续进行连接和运行,不影响运行结果。
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p39

为自己的垃圾代码辩解
教唆初学者放过警告
严重地误导初学者
3.2数据的表现形式及其运算

P39
3.2 数据的表现形式及其运算
……
3.2.1 常量和变量
……
(1)整型常量。如1000,12345,0,-345等都是整型常量。
————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p39

首先“整型”这个词含义是不明确的,在谭书中一直有n种并存的含义
其次,-345不是常量,而是常量表达式。如果可以把-345说成常量,那么3-4也可以说成是常量。岂不荒谬

P39
(2)实型常量。有两种表示形式:————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p39
老谭既然号称“按照C语言的新标准C99进行介绍”,怎么会写出实型常量有两种表示形式这样的胡话?
这只能说明老谭对C99缺乏最基本的了解
还是老作风:信口开河
P39

(3)字符常量。有两种形式的字符常量:
①普通字符,用单撇号括起来的一个字符,如:‘a’,‘Z’,‘3’,‘?’,‘#’。不能写成’ab’或’12’……字符常量只能是一个字符,……。————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p39
这一页上的第6个硬伤。

P37

评:开场白讲了两件事:作者对如何学习编程的看法,介绍该书的做法。与该章的主题没什么关系。前者在第二章已经说过,后者应该是前言或第一章的内容,写在这里有没话找话自吹自擂之嫌。
作者对如何学习编程的看法基本是片面、偏颇及错误的,是对Wirth“算法+数据结构=程序”的曲解和错误发挥。这对学习者是一种根本上的误导。

评:两个例子从问题的提法到最后的代码都糟糕透顶、漏洞百出。这两个例题给学习者带来的负面影响有很多。从这两个例题中学习者不可能领悟到究竟什么是顺序程序设计,更不可能领悟到究竟什么是程序设计。他们很可能误以为编程就是把代数式写成表达式 + 进行函数调用。
更严重的是,谭书居然告诉读者“警告”可以作为正常来接受,这是教唆式的误导。

例3.1 有人用温度计测量出用华氏法表示的温度(如69°F),今要求把它转换为以摄氏法表示的温度(如20°C)。
评:这个题目看似描述的平易近人通俗易懂。但我想小学语文老师会评价说,温度就是温度,和“有人”或没人、用或不“用温度计测量”有什么关系?“有人用温度计测量出”完全是废话。而小学数学老师会说,谭同学,69°F根本不是20°C。
这就是老谭。有人说他的书通俗易懂,其实多半只是似是而非且毫无内容的废话甚至病句而已。如果阅读不仔细很容易被他的似是而非唬过去,但只要稍微一推敲,立刻就能把他戳出几个洞。赞赏他的书的人,通常小学数学和小学语文都不咋样
此外,在题解中有这样一些毛病:
把算法说成是找公式
流程图写输入,但代码中是赋值运算
代码使用不合适的数据类型
容易出错的代码风格
……

3.2 数据的表现形式及其运算
评:这部分总的来说就是概念不清,逻辑混乱

3.2.1 常量和变量
1.常量
“常用的常量有以下几类:(1)整型常量……(2)实型常量……(3)字符常量……(4)字符串常量……(5)符号常量”
2.变量
3.常变量
4.标识符
评:从这个标题结构很容易发现其荒谬,总体来说就是不伦不类:
把标识符和常量、变量并列;把“常变量”和“变量”并列;
对常量的分类同样是不伦不类
先介绍“符号常量”后介绍“标识符”是本末倒置

此外还有如下错误
3.2.1 之 1.常量 部分
“整型常量。如1000,12345,0,-345等都是整型常量。”,这里把“-345”这个常量表达式说成了常量
刚说完“十进制小数形式,由数字和小数点组成”,立刻给出了“-56.79”这个例子,明显自相矛盾。试问,“-”是数字还是小数点?
对字符常量和符号常量的讲解均存在错误。

3.2.1 之 2.变量 部分
对编程最重要的概念之一——变量的介绍存在惊人的致命错误(“变量名实际上是以一个名字代表的一个存储地址”)
“C99允许在函数中的复合语句(用一句花括号括起来)中定义变量。”属于用C89的知识冒充C99

3.2.1 之 3.常变量 部分
把const 变量想当然地说成是C99的,实际上C89就有const 这个关键字

3.2.1 之 4.标识符 部分
介绍的是过时(对于C99来说)的说法
P39~41
评:这一小节讲的是“常量”
除了前面提到的错误、概念或知识缺失、含糊不清、误导等
回过头来看还会因为分类错乱而感觉很滑稽
(1)整型常量
(2)实型常量
(3)字符常量
(4)字符串常量
(5)符号常量
这完全是一脚天上一脚地下,关公战秦琼式的写法
p40
③ 转义字符……'\t’代表将输出的位置跳到下一个tab位置(制表位置),一个tab位置为8列
评:tab位置是实现定义的
表3.1 转义字符及其作用


转义字符 │ 字符值 | 输出结果


\'           |     一个单撇号(')   |      具有此八进制码的字符   

\"          |     一个双撇号(“)   |     输出此字符   

……

评:对“’ ”输出结果的描述不知所云

p40
字符串常量是双撇号中的全部字符(但不包括双撇号本身)
评:这个表述很似是而非
没有讲清String literal的本质
如果是讲述String literal中的字符,那么忽视了还有一个’\0’

单撇号内只能有包含一个字符, 双撇号内可以包含一个字符串。

前半句是错的,后半句看不懂究竟想说什么。
p41
(5)符号常量。……
#define PI 3.1416
经过以上指定后,本文件中此行开始的所有的PI都代表3.1416。在对程序进行编译前,预处理器先对PI进行处理,把所有的PI全部置换为3.1416。
评:成问题的地方在“所有的”那三个字,这给人以严重的误导。至少我见过读了这句话之后试图替换“……PI ……” 或v_PI中的PI的学习者。
p41
2.变量
评:这一小节错得很不靠谱
已经突破了信口开河的境界达到胡说八道的高度了
例如
C99允许在函数中的复合语句(用一句花括号括起来)中定义变量。
C99允许使用常变量,如:
const int 3=3;

我注意到本书到此为止关于C99的论述至少有九成都是错误的
而且这些错误并没涉及到什么复杂的概念,只涉及一些简单的基本常识
在这些常识性的地方居然大错特错
那么就有理由怀疑老谭究竟看过C99没有(哪怕是粗略地看过)
根本没看过C99就在书里自称“按照C语言的新标准C99进行介绍”
这不是学识问题
是品质问题
p41
请注意变量名和变量值这两个不同的概念,……
评:实际上这两个概念有时是同一的,是区分不开的。
而且老谭根本也没有讲清楚这两个概念的区别究竟何在
p41
变量名实际上是以一个名字代表的一个存储地址。
评:这是简直是胡扯!
假如有
int i;
如果 i 代表地址,那么 &i 又是什么呢?

p41
C99允许使用常变量

评:且不谈“常变量”这个翻译有多么拙劣
const关键字早在C89中就有了
关C99什么事
P42
常量是没有名字的不变量。
评:常量就一定没有名字吗?显然不是
P42
定义符号常量是用#define指令,它是预编译指令,它只是用符号常量代表一个字符串,……
评:“字符串”这个词在C语言中是有特定含义的,这里使用这个词明显不当
P42
C语言规定标识符只能由字母、数字和下划线3种字符组成,
评:不是号称“按照C99介绍”的吗?
C99是这样规定的吗?!
麻烦老谭自己亲自去看看
不要把几十年前的规定拿来冒充C99
P42
3.2.2 数据类型
评:数据类型是C语言最基础最根本性的东西。对数据类型的理解程度基本上决定了一个人C语言的水平。同样一本书对数据类型的介绍是否准确全面也在很大程度上决定了书的优劣。下面来看看谭书对数据类型的介绍。
P42
所谓类型,就是数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式。不同的类型分配不同的长度和存储形式。
评:除了最后一句是病句以外,这段话最大的毛病在于并不全面,仅仅把数据类型理解为数据在存储单元中的表示形式大约只理解了数据类型全部含义的45%。纵观全书,这个毛病始终存在。这一点我认为是谭书一个致命的硬伤。由于这个致命的硬伤,所以这本书的错误并非象有些天真的人们以为的那样可以通过修修补补改好——因为根本性的基调就是不准确和错误的。

该书把数据类型分为“基本类型”、“枚举类型”、“空类型”和“派生类型”。(表 3.4)
这也是要命的,反映了作者对数据类型的一知半解并且根本不懂得数据类型的重要性。
首先“枚举类型”与“基本类型”、“派生类型”并列是不伦不类的半调子分类。回顾本书的前几版,这个“枚举类型”的位置始终很尴尬,有时根本没有,有时与“整型”、“字符型”、“实型”并列。作者一直把“枚举类型”当作临时工一样今天放这,明天放那,后天还可能给解雇了。这些说明作者这几十年一直没能把数据类型搞清。

表 3.4中的另外几个错误是
缺乏不完全数据类型,只写了一个void类型
*布尔型(bool) ,这个写错了,再次表明老谭根本没读过C99,但他却宣称“按照C99进行介绍”,品质问题。
浮点类型中缺少long double。
复数浮点型(float_complex,double_complex,long long_complex):这个非但不全,而且全错。

仅仅这一张表上就有如此多的严重错误,这本书绝对是垃圾到家了

P42
3.2.2 数据类型
评:“为什么在用计算机运算时,要指定数据的类型呢?”这个设问的可笑之处在于后面根本没有回答,而是驴唇不对马嘴地瞎扯了一通。

“所谓类型,就是数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式。不同的类型分配不同的长度和存储形式。”
表明作者根本不懂得数据类型的含义。

把数据类型分为“基本类型”、“枚举类型”、“空类型”和“派生类型”(表 3.4)。很荒唐
更荒唐的是一口气写错了4个描述类型的关键字

3.2.3 整型数据
评:概念不清,逻辑混乱。(比如,整型变量的符号属性)纠结于具体编译器下各数据类型的空间(范围)和所谓的“补码”,并没有真正讲清楚数据类型本质性的东西。
一些原则性的错误:
在将一个变量定义为无符号整型后,不应向它赋予一个负值,否则就会得到错误的结果。
变量值在存储单元中都是以补码形式存储的

3.2.4 字符型数据
评:“因此C99把字符型数据作为整数类型的一种”,信口开河。
p43
例如,Visual C++ 6.0为char型(字符型)数据分配1个字节,
评:居然是“例如”!
敢问老谭你能否找到一个“例外”?
p44
3.2.3 整型数据
1.整型数据的分类
本节介绍最基本的整型类型。
(1)基本整型(int型)
编译系统分配给int型数据2个字节或4个字节(由具体的C编译系统自行决定)。如Turbo C2.0为每一个整型数据分配2个字节(16个二进位),而Visual C++为每一个整型数据分配4个字节(32位)。在存储单元中的存储方式是:用整数的补码(complement)形式存放。
评:这段中“整型”的含义是前后不一的,这是最基本的逻辑错误:概念不清,其后果必然是逻辑错乱
“编译系统分配给int型数据2个字节或4个字节”:字面意思是int类型只可能有两种可能,这也是错误的。
“在存储单元中的存储方式是:用整数的补码(complement)形式存放”:这是一相情愿的想当然
p44
在存放整数的存储单元中,最左面一位是用用来表示符号的,如果该位为0,表示数值为正;如果该位为1,表示为负。
评:1. unsigned 算不算整数? 哪位表示符号?
2. 什么叫“最左面一位”,拜托,那叫“高位”
3. 0000 0000 “表示数值为正”吗?乱
p44
1.整数类型的分类
(1)基本整型(int型)
(2)短整型(short int)
(3)长整型(long int)
(4)双长整型(long long int)
评:最多是对Turbo C2.0和Visual C++6.0的情况进行反复举例而已,并且错误地把补码、一个字节8位这一特殊情况作为了唯一情况
p45
编译系统分配给long数据4个字节

评:又是想当然
p45
2.整型变量的符号属性
评:这是个不通的标题。暂且不说“符号属性”这个概念是否恰当,即使真有“符号属性”这个概念,那么它也是数据类型的性质,而不是“变量”的性质
p45
以上介绍的几种数据类型,变量值在存储单元中都是以补码形式存储的
评:胡扯!
p46
因此无符号整型变量中可以存放的正数的范围比一般整型变量中正数的范围扩大一倍。
评:抛开语文等方面的问题不谈
就以两个字节的补码表示形式的int以及unsigned来说
int:1~32767
unsigned:1~65535
这难道是扩大一倍吗?
老谭显然掰不开正数和非负数这两个概念的区别
p46
(2)对无符号整型数据用%u输出。%u表示用无符号十进制数的格式输出。如:
unsigned short price = 50 ;
printf(“%u\n”,price);
评:不否认能输出正确的结果
但是“对无符号整型数据用%u输出”显然是荒谬的
这里的“整型”是个集合概念还是个体概念?
如果是集合概念,陈述显然是错误的
如果是个体概念(unsigned int)怎么可以用short举例呢
老谭显然根本不清楚printf(“%u\n”,price)函数调用中的price表达式的真实类型
输出正确结果其实是张冠李戴之后瞎蒙碰出来的结果

“无符号十进制数”也属于莫名其妙的说法
老谭好像是在自言自语地说着自己才仿佛懂得的话
p47
在将一个变量定义为无符号整型后,不应向它赋予一个负值,否则就会得到错误的结果。如:
unsigned short price = - 1 ;//不能把一个负整数存储在无符号变量中
printf(“%d\n”,price);
得到的结果为65535.显然于原意不符。
思考:这是为什么?
原因是:系统对-1先转换成补码形式。就是全部二进制位都是1(见图3.8),然后把它存入变量price中。由于price是无符号短整型变量,其左面第一位不代表符号,按%d格式输出,就是65536.

price
1111111111111111
图 3.8
评:这段短短的文字至少有四个错误
找出3个C语言算入门了

p47
3.2.4 字符型数据
由于字符是按其代码(整数)形式存储的,因此C99把字符型数据作为整数类型的一种。但是,字符型数据在使用上有自己的特点,因此把它单独列为一节介绍。
评:1.代码、编码,两个概念。老谭这个“代码”大概是翻译软件翻译的吧
2.字符类型作为整数类型的一种,C89就已然如此,和C99有什么关系。老谭这是在不懂装懂地蒙人
3.每种数据类型都有自己的特点。在这点上,字符型数据没什么特殊的
p47
字符与字符代码并不是任意写一个字符,程序都能识别的。
评:这是人话吗
主语是什么
谓语是什么
宾语又是什么
程序识别什么
p47
例如圆周率π在程序中是不能识别的,只能使用系统的字符集中的字符集,目前大多数系统采用ASCII字符集。
评:谁说π就是圆周率的?
什么叫“识别”
什么“系统”
“字符集”有几套?
“大多数系统采用ASCII字符集”吗?
前面有网友说老谭无论对C89还是C99都还没入门
确实一针见血
p47
在将一个变量定义为无符号整型后,不应向它赋予一个负值,否则就会得到错误的结果。如:
unsigned short price = - 1 ;//不能把一个负整数存储在无符号变量中
printf(“%d\n”,price);
得到的结果为65535.显然于原意不符。
思考:这是为什么?
原因是:系统对-1先转换成补码形式。就是全部二进制位都是1(见图3.8),然后把它存入变量price中。由于price是无符号短整型变量,其左面第一位不代表符号,按%d格式输出,就是65536.

price
1111111111111111
图 3.8
评:向无符号整数类型变量赋值,C语言是有定义的。不是什么错误的结果。不能因为自己不理解C语言的真正语义就说那是错误的
printf(“%d\n”,price);得到的结果为65535 。不是什么与“原意不符”,而是作者根本不懂得那段代码的真正含义(尤其是其中存在的类型转换)
C语言没说一定采用补码
那个price其实并不是unsigned short,而是一个int类型
……
此外很多不严谨的地方就不多说了

p48
字符是以整数形式(字符的ASCII代码)存放在内存单元中的。
评:C语言从来没说过只处理ASCII码
p48
所以在C中,指定用1个字节(8位)存储一个字符(所有系统都不例外)
评:据我所知,有的系统的1字节是9位
老谭你怎么解释这个“所有系统都不例外”
p48
2. 字符变量
字符变量是用类型符char定义字符变量。
评:这是人话么?

p48
字符变量是用类型符char定义字符变量

这是话么?
这就是简介说的“文字流畅”?
当然
与以前的“字符型变量用来存放字符常量”还是天壤之别
以前的是错话
现在的是废话

(1)+、-、、/运算的两个数中有一个数为float或double型,结果是double型,因为系统将所有的float型数据都先转换为double型,然后进行运算。
评:一句不长的话错了两次。
1.“+、-、
、/运算的两个数中有一个数为float或double型,结果是double型”
老谭既然在前面吹嘘这本书是“按照C语言的新标准C99进行介绍”
难道不知道C语言有复数类型吗?
如果“+、-、*、/运算的两个数中有一个数为float或double型”,另一个是复数类型,“结果是double型”吗?

就算你根本不懂得C99
虚张声势地出来蒙人
long double 类型可是几十年前就有了
如果“+、-、*、/运算的两个数中有一个数为float或double型”,另一个是long double,“结果是double型”吗?

2.“系统将所有的float型数据都先转换为double型,然后进行运算。”,简直是胡扯

(2)如果int型与float或double型数据进行运算,先把int型和float型数据转换为double型,然后进行运算。结果是double型
评:第一次读完这个(2),我愣住了,简直不敢相信
再仔细看一遍,发现这个(2)真的是很(2)
因为什么呢
因为(1)已经说过“+、-、*、/运算的两个数中有一个数为float或double型”
现在(2)居然又开始大谈特谈“如果int型与float或double型数据进行运算”
车轱辘话来回说是老谭的一个特点
但刚说完就repeat一遍还是罕见的
中等程度的神经错乱都写不出来这种东西

而且,char 、long等与float或double型数据进行运算的情况,阙如

这段中的严重错误就不谈了
与错乱相比,错误简直不算什么了不起的事情

(3)字符(char)型数据与整型数据进行运算,就是把字符的ASCII代码与整型数据进行运算。如:12 + ‘A’,由于……
评:前面说的是“字符(char)型数据与整型数据进行运算”
立刻就拿出个两个 int 类型数据的加法来举例
很明显
老谭根本不知道 ‘A’ 的类型究竟是什么

评:暂且不谈C语言的执行环境未必使用ASCII码的问题)
这里的“整型数据”是个莫名其妙的概念

在该书的43页写到
| 基本整型 (int)
| 短整型 (short int)
| 长整型 (long int)
整型类型 | *双长整型 (long long int)
| 字符型 (char)
| *布尔型 (bool) [注:这里的bool也是错误的]

所谓“字符(char)型数据与整型数据进行运算”
说的到底是哪种"整型类型"呢?
况且这根本就是一个不必要的条件限制
难道 char类型数据 与 double类型数据 做加法运算时那个char类型数据不是字符编码吗?
它不是字符的编码还能是什么别的东西吗?

字符数据可以直接与整型数据进行运算。
评:不知所云。
什么叫“直接”进行运算?
是否还有“间接”进行运算?

⑤将10+‘a’+i*f的结果与d/3的商2.5相减,……
评:1. “实型数据”,应为(实)浮点型数据。因为在C语言中real types是整数类型与(实)浮点类型的合称。
2.“字符的ASCII” ,运行环境中的字符不一定是用ASCII码表示的。况且,即使运行环境也使用ASCII码,字符数据中存储的也不一定是ASCII码。比如,字符数据可能是一个负值
3.“转换为double型数据” ,完全无视了integer promotions。而且最终可能转换成三种而不是只有double这一种。
紧接着

以上的转换是编译系统自动完成的,用户不必过问。
评:不知所云。

分析下面的表达式,假设已指定i为整型变量,值为3,f为float型变量,值为2.5,d为double型变量,值为7.5 。
10+‘a’+if-d/3
编译时,从左到右扫描,运算次序为:
①进行10+'a’的运算,……
②由于“
”比“+”优先级高,先进行if的运算。先将i和f都转成double型,……
③整数107与i
f的积相加。
④进行d/3的运算……
⑤将10+‘a’+i*f的结果与d/3的商2.5相减,……
评:最雷人的是: “编译时……运算次序为”
编译时就运算,那运行时计算机干些什么呢?

“②由于“”比“+”优先级高,先进行if的运算”
可是“进行10+'a’的运算”为什么先做了呢,
难道“*”比第1个“+”优先级低、比第二个“+”优先级高吗?

“先将i和f都转成double型”
错的。

小学语文问题:
“if的积”,
“将10+‘a’+i
f的结果与d/3的商2.5相减”

4.不同类型数据的混合运算
……如果一个运算符的两侧的数据类型不同,则先自动进行类型转换,使两者具有同一类型,然后进行运算。
评:若有
int a[1];
那么对于表达式
*( a + 0 )
显然“+”“两侧的数据类型不同”。
老谭能否给解释一下,如何“自动进行类型转换”?使两者具有了什么样的“同一类型”?

3.算术表达式和运算符的优先级和结合性
用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子,
称为C算术表达式。运算对象包括常量、变量、函数等。例如,下面是一个合法的C算术表
达式:
ab/c-1.5+‘a’
C语言除了规定了运算符的优先级外,还规定了运算符的结合性。在表达式求值时,先
按运算符的优先级别顺序执行,例如先乘除后加减。如表达式a-b
c,b的左侧为减号,右
侧为乘号,而乘号的优先级高于减号,因此,相当于a-(b*c)。
如果在一个运算对象两侧的运算符的优先级别相同,如a-b+c,则按规定的“结合方
向”处理。C语言规定了各种运算符的结合方向(结合性),算术运算符的结合方向都是“自
左至右”,即先左后右,因此b先与减号相结合,执行a-b的运算,然后再执行加c的运算。
“自左至右的结合方向”又称“左结合性”,即运算对象先与左面的运算符结合。以后可以看
到有些运算符的结合方向为“自右至左”,即右结合性(例如,赋值运算符,若有a=b=c,按
从右到左的顺序,先把变量c的值赋给变量b,然后变量b的值赋给a)。关于“结合性”
的概念在其他一些高级语言中是没有的,是C语言的特点之一,希望能弄清楚。附录D列
出了所有运算符以及它们的优先级别和结合性。
评:首先,来看一下引用部分小标题里的第一个词——“算术表达式”。
这个词很给人一种“亲切感”特别有迷惑力,然而它确是一个模糊的、似是而非而且毫无用处的概念。
据我所知,这个词是老谭自创的。C语言中并没有这样的概念。
C语言中只有算术类型(arithmetic types)和算术运算符(arithmetic operators)这样的概念,并没有“算术表达式”这种概念。
没有这样的概念,难道不可以自己创造概念吗?当然可以。但必须知道的是,创造概念是有前提的:

创造者要给出概念的定义;

概念要科学严谨;

这个概念有用,或者方便简洁地描述了一个道理,或者帮助别人认识了一类现象或规律。

这样才可以创造新概念。
不满足这三个前提,自创概念不是吃饱了撑的就是假行家故弄玄虚的蒙人行为。考察一下“算术表达式”这个概念。
作者给出了定义:“用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称为C算术表达式。”
(很好,老谭自创概念不给定义的例子比比皆是,这次很有进步)
然而,这个概念并不科学,也不严谨。为什么这么说呢?简单地考察一下下面的表达式就会知道了:
1+(2+3)
在这里,如果把“+”说成是“连接”“操作数”还是勉强说得过去的,但是“()”的意义则绝对不是为了“连接”“操作数”。“()”的意义是为了表明其内部的子表达式作为一个整体——仿佛一个独立的操作数参与运算,这与“连接”是八竿子打不着的。再比如“(1)”这个表达式中,“()”连接了什么呢?其实它什么也没连接,它只表明它与其扩起来的部分是一个完整的整体而已。
所以说,这里的“()”是一种“界定”(to delimit)范围的符号,把它与表示运算的运算符并列在一起是很荒唐的。
作者接着补充道:“运算对象包括常量、变量、函数等”。
这就让人迷惑不解了,这里的“函数”究竟是指的什么呢?是“函数调用”还是“函数名”本身呢?如果是“函数调用”,就成了自己打自己耳光,因为函数调用一定是通过函数调用运算符“()”实现的(注意这里这个"()"不是括号),这和作者在前面说的“用算术运算符和括号将运算对象(也称操作数)连接起来的”自相矛盾。如果这里的所谓“函数”是“函数名”的话,总所周知,“函数名”这种数据类型怎么可能进行算术运算呢?
所以必须感谢作者的及时补充,他成功地使用“函数”这个词戳穿了他自己创造的伪概念——“算术表达式”,这个概念是经不起推敲的。
紧接着的“例如”也很成问题。权且承认他给出“a*b/c-1.5+‘a’ ”是合法的,但是这个表达式即不是“用算术运算符和括号将运算对象(也称操作数)连接起来的”(因为没有括号),“运算对象”也不“包括常量、变量、函数”(“函数”在哪?),作者举例到底想说明什么呢?无厘头么!

  • 作者:C?est bien d?�tre seul
  • 原文链接:https://blog.csdn.net/qq_46699502/article/details/124337182
    更新时间:2023年4月27日12:09:43 ,共 22518 字。