掛羊頭賣狗肉蓄意欺騙讀者——譚浩強《C程序設計(第四版)》中所謂的“按照C99”(二)
在《譚C》p4:“本書的敘述以C99標准為依據”,下面從C89到C99的主要變化方面來看看是不是這樣。
- 《譚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。
- 《譚C》(前言)p12:
② C99要求,main函數的類型一律指定為int型,並在函數的末尾加一個返回語句“return 0;”。
實際上,main函數的類型一律指定為int型是C89的要求,並且C99標准並沒有要求在main()末尾必須寫語句“return 0;”。
- 《譚C》p5:
C99又擴充了……布爾類型(bool)等。
實際上,C99增加的是_Bool類型。
- 《譚C》p6:
C99建議把main函數指定為int型(整型)。
C99根本沒有這樣建議。
- 《譚C》p39:
“(2)實型常量。有兩種表示形式”
實際上在C99中還有hexadecimal-floating-constant常量。
- 《譚C》p41:
“C99允許在函數中的復合語句(用一句花括號括起來)中定義變量。”
C語言從誕生至今一向如此,這跟C99半毛錢關系都沒有。
- 《譚C》p41:
“C99允許使用常變量。”
const關鍵字C89就開始有了,而且“常變量”這個翻譯很蠢。
- 《譚C》p42:
“C語言規定標識符只能由字母、數字和下划線3種字符組成。”
實際上C99規定標識符還可以由universal-character-name和other implementation-defined characters組成。
- 《譚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有復數類型,如果“+、-、*、/運算的兩個數中有一個數為float或double型”,另一個是復數類型,結果不可能是double型。
況且,即使是C89,如果一個操作數是float另一個是long double 類型,結果也不可能是double。
15.《譚C》p107:
“程序4:可以在程序中使用C99提供的邏輯變量和邏輯常量true和false……
#include <stdbool.h>
……
注意:目前一些C編譯系統(包括Visual C++6.0)還未完全實現C99標准,因此不能運行程序4……可把作為C++程序來運行(C++有些功能),把文件名后綴改為.cpp。並將第1、2行改為
#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”出版是對讀者的欺騙。這不是學術水平問題,而是道德品質問題。