《狂人C》讀評(一) 理解程式設計篇

來源:互聯網
上載者:User

KBTiller兄在書籍扉頁寫指正,不敢指正,共同討論。其實第一篇在年前已看完,由於過節心態浮躁一直沒能總結記錄。仔細想想自己真是拖拉的要命,再不寫點東西對不起KBTiller兄的熱情心意。本文大部分內容屬於跟作者觀點不一致的描述,我不是初學者,所以與其是讀書筆記,不如說挑刺,儘管這樣,書中還是有不少讓我受益良多的地方。為了整理方便,主體內容分四個不同的部分,有的問題分界比較模糊,主觀因素比重很大。至於為什麼會這麼長,那是因為我吹毛求疵了 :)。

一、精彩絕倫:我認為的很出彩的地方

1、最精彩的地方就是作者對細節對技術本質的探索,這點讓我肅然起敬,這才是一個工程師應該具備的最高的品質。
2、P22 這個NEO畫的真神了(KBTiller兄你想累死初學者麼 ^^)。
3、P27 本文第3段第1行 “從這兩條規則中發現在代碼中只能寫成正的十進位整數常數”,以前一直沒有發現這點,讀到這裡真是如醍醐灌頂!P39的練習也是這個道理。
4、強調資料類型為基本是本書在技術上最特色的閃光點,資料類型的確是C語言的複雜所在,也是最難正確理解和使用地方,在我讀的任何一本C語言書籍中還沒有能系統的提及此,作者幾乎對每個類型都做了深入分析,贊!
5、P71-P73 專門講解了優先順序結合性和運算次序的關係,這也是C語言中非常讓人迷惑的地方,很多學了三五年的熟手還經常會犯錯誤,歸根結底就是當初基礎沒打好,這裡非常專業的分析了它們之間的關係,協助初學者避免很多問題,這是很多C語言書籍尤其是國內教科書最欠缺的地方。
6、把=讀成賦值,這個主意的確非常棒。
7、P111利用判斷三角形種類這個問題來鍛煉讀者的邏輯判斷能力是非常恰到好處的。初學者對代碼的理解和控制不夠熟練,往往會出現邏輯混亂的狀況,這時候正需要加強練習。
8、P142用了小4頁來講解++ -- 運算子,幫”教授“和”專家“們的學生排除遺毒,作者大人辛苦了!

二、知識錯誤:知識點出錯或者遺漏的地方

1、P7本文第4段第1行 “1987年87 ANSI C公布”,根據我在維基百科和C參考手冊上的資料得知,ANSI C委員會是在1982年籌建,1983年正式成立的,而在1989年推出了ANSI C標準,俗稱C89,這裡是應該是錯誤了。
2、P13本文第8段第8行 “其中的字元都原樣輸出,除非出現“/”引導的字元序列或“%”引導的字元序列” 除了/和%引導的字元序列外,??引導的三字元序列也會被轉換,儘管這個傢伙幾乎被遺忘了。
3、P13代碼第3塊第一行 “/" 、/n 、/a 、/b 、/t 、// 、/" 、/'”,這裡怎麼多了一個/",而且少了/v /f /r /? ,這屬於字元轉義符,還有別的轉義符,描述不夠精確。P49也有這個問題。
4、P14腳註1 “目前好像還沒有實現可以使用漢字的C語言編譯器” P16腳註1也是。VS2008中文版支援中文字元作為標識符,當時發現了這個的緣故是自己define出來一套漢編。看到這個,再版書籍的時候會不會考慮使用VC++ Express作為首選IDE呢,呵呵。
5、P24本文第4段第2行 “稱呼這種編號的專業術語有很多種,有的叫ASCII碼,有的叫內碼,有的叫Unicode編碼” ASCII碼和Unicode編碼都是內碼的一種(如果英文也有內碼這種說法的話),在這裡把他們並列起來描述不適合,應該把內碼刪掉,換成其他的,如GBK/GB2312。
6、P48本文第4段第3行 “所以 signed是可以省寫的這一說法,如果不說是錯誤的,那麼至少是不嚴謹的。” 其實就是錯誤的,不能省略,在函數的聲明和定義中如果一個使用 signed char 一個使用 char ,gcc下會編譯出錯,這點在CU論壇上也討論過了,不多做解釋,詳細見連結:http://bbs.chinaunix.net/thread-1834841-2-11.html 從17樓開始,中有素質低下者請自動無視。
7、P82本文第10段第1行 “在{}之內,C99以前的規定是先把對編譯器的事兒說完,再說讓CPU做的事。也就是說要先寫聲明,再寫語句”。C89也沒有這個規矩阿,大概是K&R的C才會有這個要求(K&R要不要求我還真不清楚,但TurboC會要求)。

三、表述不當:在書中出現的位置不對或者容易引發歧義或者筆誤疏漏的地方

1、P3本文第2段第1行 “通常我們所看到的電腦,一般都會有鍵盤、滑鼠、顯示器、機箱等幾個部分”。這裡講機箱並不太合適,畢竟機箱只是一個空殼子,裡面的內容才是最重要的,所以把“機箱”改成“主機”更適合。
2、P6本文第21段第1行 “組合語言用助記符(add ,move)”,前面給出的例子是用的mov,但這裡寫出來是move,還是統一更好。
3、P7本文第4段第2行 “這個標準在1990年被國際標準組織(International Standards Organization,ISO)”,ISO的英文標準名字是International Organization for Standardization 雖然看起來很古怪(貌似縮寫成IOS更合適 --!)而且在後面P47也是用的International Organization for Standardization,所以這裡要統一下。
4、P9本文第3段第1行 “由於使用了一段事先寫好的程式段(這是編譯器提供的)”。在這裡說的是printf庫函數,庫函數不是編譯器的一部分,但初學者又不知道啥叫函數庫,所以建議改成“這是隨編譯器一起提供的”。
5、P16本文第8段第3行 “如表1-1所示,是C99新增的關鍵字。” 但是表1-1給出的是C99全部關鍵字,只有被加了標註的才是新增關鍵字,而且文法也有點問題。所以這裡個人建議更改為“表1-1是C99全部的關鍵字。”
6、P20練習2.6 “使用printf()函數應在代碼開頭的位置通過編譯是編譯器處理命令對函數的名稱做相應的說明“。 “編譯是”應該是筆誤。
7、P25本文第3段第2行 “在123後面寫;是因為123無法被單獨寫在代碼中。” 這句話理解起來不太得勁,建議改成“無法單獨作為一句代碼”更好。
8、P32本文第2段第1行 “記憶體(Memery Unit)這個詞,本來就是記憶器件的意思。” Memery Unit最好翻譯成記憶體單元,畢竟後面跟了個Unit。
9、P36本文15段第1行 “求一個負數的補碼,還可以用2^機器數的總位元 減去這個數直接得到。” 減負等於加正,所以應該是“加上這個數直接得到”。
10、P49代碼第5塊 “/八位元 /x十六進位數” ,C語言對逸出字元的長度還是有要求的,八進位不能超過3個,十六進位不超過2個,這應該在後面寫上。
11、P60本文第6段第2行 “然而12/10用%2d輸出的是1,也就是說不會輸出1前面的0,如果希望輸出為02,則在%與2d之間應再在寫個0——%02d” ,這裡應該是要輸出01,筆誤寫成02了。
12、P65習題12.“輸入一社會安全號碼碼,輸出這個人的生日。” 之前沒有講任何輸入函數,所以這道題不適合在這裡出現。
13、P67本文第3段 運算子介紹,有尾碼運算子,但是沒有說首碼運算子。
14、P69本文第3段第1句,“在這個運算式中,賦值號右面的運算式中的...” 前面一直把=稱為賦值運算子,在這裡忽然冒出個賦值號,不和諧阿。
15、P73腳註2 “利用續行的標誌,從某種意義上說,單調也可以割裂”,“單詞”筆誤成“單調”,這裡瞬間聯想到嚴謹而又慈祥的高數老師。
16、P75本文11段第3行 “不要對cast運算有更多想入非非的非分之想”, 非分之想已經有想入非非的意思,再加上這個就顯得太囉嗦,可以把想入非非去掉。
17、P84代碼使用了scanf語句,這是本書第一次提到這個語句,但是沒有任何講解,建議解釋下scanf的基本用法,簡單的可以說下代碼中出現的用法。
18、P128圖4-6”程式開發過程“ 這個圖除了注釋用的橢圓外看起來跟程式流程圖差不多,有個結束框,但是開始框在哪裡呢?為了確保完整性和一致性建議把開始框加上。
19、P131本文第7段第1行 “如果運算式的值不為0,執行語句,然後轉至(0)再次求運算式的值” 上面沒有(0)這一項,筆誤了,應該是(1)。P138也有此錯誤,浮想聯翩。
20、P136本文第3段第3行 “測試結果表明,輸入0整數時,程式的運行是有問題的。” 這裡少了一個字,應該是“輸入0個整數“。
21、P137代碼第2塊第1行 ”while (printf("....")) /“ 這句代碼後面有一個”/“ ,但是這裡不用這個轉義符代碼也不會出錯,顯得多餘了,/一般都是用到宏上。
22、P146本文第5段第3行 “畫虎不成反成犬”,無論從用詞還是用google得到的結果來看都是“畫虎不成反類犬”更適合 ^^
23、P149代碼第14,15行 見上面第21點。
24、P150本文第4段第2行 “此外for語句()內的運算式2部分也寫的更簡潔了。” 這裡不唯寫的簡潔,而且減少了判斷次數,增加了運行效率,這點我認為也可以提一下。
25、P158本文10段第1行 ”序點之前要求電腦執行的運算及副效應在序點處必須完成“ 聽起來怪怪的,這樣如何:”電腦執行的運算及副效應在序點前必須完成“。

四、觀點差異:不算錯誤,但是主觀差異較大的地方

1、P9 腳註3 “使用IDE需要冒著被指責為菜鳥的風險,有些高手更喜歡錶明自己不使用IDE而使用一些更為原始的開發環境。但總的來說,使用IDE開發軟體更為方便。” 這句話我是贊同的,對於初學者來說IDE可以隱藏很多繁瑣的細節,但有些細節對以後的發展會很重要,例如編譯和連結。只有使用了命令列才會真正瞭解編譯參數和連結過程,這是絕大部分C語言入門書籍沒有教導,甚至沒有提及的(大概跟平台差異性太大有關)。但是我覺得還是有必要在適當的時候提出一下(例如後面講標準庫的時候,或者把編譯和連結作為進階課題專門開一章),不然初學者就根本忘記了有這麼回事。
2、P32本文13段第1行 “變數是一段連續的、被命名了的、用於存放資料的、且可以求得其位置的、具有類型含義的儲存空間” 這裡有個比較特殊的變數是register變數,register變數是不能取地址的,因為它可能存在寄存器而非記憶體中。知道它存在寄存器(但不知道哪個編號的寄存器)算不算知道了位置了呢?這就是個見仁見智的問題。
3、從P71至P84,中間講述了運算子優先順序、結合性、類型轉換、語句的各種概念這種純理論的要點,個人覺得這些知識點太密集了,而且中間實際例題(完整代碼的例題)也很少,這樣給初學者壓力很大,建議還是中間插入寫例題緩和下進度,或者把知識點分散到別的章節。
4、P96本文第4/5段第1句 “由於3的確小於4,所以3<4的運算結果為1” “由於4<3這個關係並不成立,所以4<3的運算得到的值為0” 這裡是第一次接觸到關係運算,讀者之前並沒有任何關係運算的概念和知識,也不知有任何因果關係,所以這裡的“由於...所以...”這種用詞不當,用敘述式的語氣更符合,但如果說是作者教導的推理也可以過得去。
5、P97 4.22 P139 5.22 標題都是 ”例題“ 這似乎不太正規,尤其是會出現在目錄中的這種大標題,建議加上個限定語。
6、P110 P111代碼塊 “if (pfh_d==1)” "if (pfh_d==true)" 這是講解_Bool類型用法的時候給的例子。但我們把一個量當作布爾類型的時候往往不會使用判等運算子,因為變數本真就有真假的含義,而不用繞一步判斷是否和真相等。所以一般都這樣寫,更簡潔更容易理解 "if (pfh_d)"。
7、P118 “大師如是說goto” 這裡有點過於倉促了,我起碼會在兩個地方用到goto 1、不同地方產生不同的傳回值,但為了確保代碼結構清晰或者返回前有統一的事情要做,只用一個return返回。 2、迴圈/switch嵌套直接跳出。關於這點在CU上也討論過了,不再多說。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.