挂羊头卖狗肉蓄意欺骗读者——谭浩强《C程序设计(第四版)》中所谓的“按照C99”(二)

挂羊头卖狗肉蓄意欺骗读者——谭浩强《C程序设计(第四版)》中所谓的“按照C99”(二)

在《谭C》p4:“本书的叙述以C99标准为依据”,下面从C89到C99的主要变化方面来看看是不是这样。

  1. 《谭C》(前言)p12:

①  数据类型介绍中,增加了C99扩充的双长整型(long long int)、复数浮点型(float complex,double complex ,long long complex)、布尔型(bool)等,使读者有所了解。

实际上,C99不但增加了long long int,还增加了unsigned long long int以及扩展整数类型;C99中压根就没有float complex,double complex ,long long complex以及bool

  1. 《谭C》(前言)p12:

②  C99要求,main函数的类型一律指定为int型,并在函数的末尾加一个返回语句“return 0;”。

实际上,main函数的类型一律指定为int型是C89的要求,并且C99标准并没有要求在main()末尾必须写语句“return 0;”。

  1. 《谭C》p5:

C99又扩充了……布尔类型(bool)等。

实际上,C99增加的是_Bool类型。

  1. 《谭C》p6:

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

C99根本没有这样建议。

  1. 《谭C》p39:

 “(2)实型常量。有两种表示形式”

实际上在C99中还有hexadecimal-floating-constant常量。

  1. 《谭C》p41:

 “C99允许在函数中的复合语句(用一句花括号括起来)中定义变量。”

C语言从诞生至今一向如此,这跟C99半毛钱关系都没有。

  1. 《谭C》p41:

 “C99允许使用常变量。”

const关键字C89就开始有了,而且“常变量”这个翻译很蠢。

  1. 《谭C》p42:

 “C语言规定标识符只能由字母、数字和下划线3种字符组成。”

实际上C99规定标识符还可以由universal-character-nameother implementation-defined characters组成。

  1. 《谭C》p42:

 “因此C99把字符型数据作为整数类型的一种”

信口开河。字符从来都是整数类型。

10.《谭C》p43:

 “布尔型(bool)

float_complex,double_complex,long long_complex”

对于C99来说,这些都属于常识性错误。

 

11.《谭C》p49:

 “浮点型数据是用来表示具有小数点的实数的 。”

C99中浮点类型包括实数浮点类型和复数浮点类型

12.《谭C》p50:

 “浮点数类型包括float(单精度浮点型)、double(双精度浮点型)、long double(长双精度浮点型)。”

这个说法证明老谭对C99还处于根本没入门的地步。C99中清楚地写着:

The real floating and complex types are collectively called the floating types

 

13.《谭C》p53:

 “两个整数相除的结果是整数,如5/3的结果值为1,舍去小数部分。但是如果除数或被除数中有一个为负值,则舍入的方向是不固定的。”

又是信口开河。来看看C99怎么讲的:

When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.

14.《谭C》p54:

 “(1)+、-、*、/运算的两个数中有一个数为float或double型,结果是double型,因为系统将所有的float型数据都先转换为double型,然后进行运算。”

错得没边了。

不要说C99不是这样,就是更早的C89也不是这样。系统将所有的float型数据都先转换为double明显是从几十年前早已过时的C语言书上抄来的。

C99有复数类型,如果“+-*/运算的两个数中有一个数为floatdouble型”,另一个是复数类型,结果不可能是double型。

况且,即使是C89,如果一个操作数是float另一个是long double 类型,结果也不可能是double

 

15.《谭C》p107:

 “程序4:可以在程序中使用C99提供的逻辑变量和逻辑常量truefalse……

#include <stdbool.h>

……

注意:目前一些C编译系统(包括Visual C++6.0)还未完全实现C99标准,因此不能运行程序4……可把作为C++程序来运行(C++有些功能),把文件名后缀改为.cpp。并将第12行改为

#include <iostream>

狗带嚼子——胡勒。公然教唆小朋友学坏,C语言和C++完全是两回事。

16.《谭C》p132:

 “从附录F中可以看到:在C库函数中,有两个求绝对值的函数”

C99中求绝对值的函数根本不是两个,附录F根本不是C99库函数,是用过时的东西欺骗读者。

17.《谭C》p143:

 “定义一维数组的一般形式为

类型符 数组名[常量表达式];”

无论从C89还是C99标准来说都是错误的

C89来说,“常量表达式”是不准确的,不是任何常量表达式都可以;从C99来说,并没有要求一定是“常量表达式”

 

18.《谭C》p143:

 “不能包括变量,如“int a[n];”是不合法的。也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。例如下面这样定义数组是不行的:

int n;

scanf("%d",&n) ;   //企图在程序中临时输入数组的大小

int a[n];”

这段代码在支持C99的编译器下没有问题。int a[n];C99中完全合法,这就是C99的一个重要新特性——VLA

 

19.《谭C》p143:

 “如果在被调用的函数(不包括主函数)中定义数组,其长度可以是变量或非常量表达式。如:

void fun(int n)

{

int a[2*n];   //合法,n的值从实参传来

……

}”

没见过这样自己打脸的。前面刚刚讲完[]内只能是“常量表达式”,一转眼又说int a[2*n];   //合法。完全是自相矛盾,

这种自相矛盾带给初学者的不止是错误还有混乱和无所适从。

如果按C89来说,这段论说是绝对错误的。

如果按C99来说这段说法依然是错误的,因为main()与其他函数相比除了是程序开始执行的位置之外没有什么特殊的,“不包括主函数”的说法完全是不懂装懂的信口开河,没有任何根据。

 

20.《谭C》p143:

 “在调用func函数时,形参n从实参得到值。这种情况称为“可变长数组”,允许在每次调用func函数时,n有不同的值。”

这又是胡扯。C99压根就没有规定VLA需要从实参得到值。

 

这里所举的例子,只是《谭C》中涉及到C99的极少的一部分而已。

从这些例子中已经不难看出,该书所谓的C99,似是而非者有之;编造关键字者有之;把非C99内容硬说成C99者有之;因对C99无知而偷工减料者有之;信口开河有之;……一句话,除了知道C99增加了一种新形式的注释和增加了long long int类型之外,该书作者根本不懂得C99

该书中涉及到C99的内容,95%以上都是错误的。这说明该作者不但没读过C99标准,甚至没读过有关C99的有关书籍或文章。整本书基本上无非是新瓶装旧酒,就如同把过期食品贴了一张新日期标签再涂点新鲜的油彩一样,大言不惭地就上市了。

作为该书的作者,对自己对于C99一窍不通的情况绝对应该是心知肚明的,因此,这种把完全过时、错谬百出的旧书伪装成“C99”出版是对读者的欺骗。这不是学术水平问题,而是道德品质问题。

 

原文地址:https://www.cnblogs.com/pmer/p/4006698.html