1. 程式人生 > >C語言學習資源大全

C語言學習資源大全

在這裡想比較系統的談談個人對C語言學習方法的理解。分別按照書籍、實驗環境搭建、網路資源來分別介紹,希望能寫的比較完整全面一些,給想學習C語言的朋友一個有價值的參考。

為什麼要學習C語言?

為什麼要學習、使用C語言?為什麼要學習一個可能比自己都歲數大的程式語言?

我在前面如何學習程式語言的部落格文章http://sunxiunan.com/?p=1597裡提到,選擇一門程式語言,“為什麼而學”這個目的是最重要的,目的不明確就沒法學好。這也是為什麼很多學生朋友在大學裡必修C語言卻覺得沒學明白的原因。因為學習的目的不明確,學習當然也沒有動力。還有一個原因是C語言是工程實踐性很強的語言,它不是來自某個研究所某個大學學院,而是實實在在從專案需要中產生,伴隨著Unix的興起而流行,語義簡明清晰,功能強大而不臃腫,簡潔而又不過分簡單,實在是居家旅行工作學習必備之良友。

C語言相比C++的優點之一就是最小驚訝,一是一二是二,不會在私底下產生一些莫名其妙的額外產物。用C++做個例子,比如這樣一個函式原型void PassWithClassValue(COneClass clsParam1),稍微瞭解C++的朋友都會知道,如果你沒有實現COneClass的拷貝建構函式,編譯器會好心的幫你實現一個,而且在呼叫這個函式PassWithClassValue的時候,偷偷地呼叫拷貝建構函式產生一個臨時物件作為引數傳遞,對於某些情況,比如編寫作業系統這類必須優化效能的情景下,這些自以為是的東西是非常邪惡的事情。

C語言本身只提供必要的語言特性,其它複雜一點功能如檔案處理、數學計算等等都以庫函式方式提供,甚至連malloc、free這種“必須有”的功能,也是以標準庫函式的方式提供,而不是作為C語言核心出現。在偉大的著名的無所不包的《K&R》開頭部分就提到了,for其實可以通過while來完成,只不過for可以寫的更簡潔,言外之意,對於C語言for其實不是必要的。跑題一點說,在其它程式語言中Lua可以說繼承了C語言簡潔的設計哲學,甚至連continue這種幾乎必備的關鍵字都一直拒絕加入,在Lua的maillist以及wiki裡都提到過continue這個問題,Lua語言維護者認為continue對於Lua而言不是必要的,也不考慮在後續版本中新增這個關鍵字。這種簡潔哲學也讓C語言的可移植性、便攜性特別優秀,也使得很多嵌入式系統依然使用C語言作為主要程式設計工作語言。

Java語言有一個口號:“一次編寫,處處執行”,就是跨平臺這個噱頭。實際上C語言從早期開始就幾乎達到了“一次編寫,處處編譯”,在ANSI在1989年統一了C語言標準以後(稱之為C89),只要特定平臺上的編譯器完整實現了C89標準,而且你的程式碼沒有使用某些特殊的擴充套件(GCC以及微軟都有自己的編譯器特定擴充套件),那麼程式碼一定可以編譯通過,再實現一下作業系統相關的函式庫,C語言的移植就是很簡單的事情。可以用Lua作為例子,Lua本身是完全遵循C89標準,沒有使用任何特定擴充套件,這也保證了有C語言編譯器的平臺,都可以編譯使用Lua。可以編譯執行C語言的硬體平臺可以從A排到Z,真是非常有意思的事情。

C語言也是一個比較少見的應用領域極為廣泛的語言。比如編寫作業系統這種高難問題,只有C++、組合語言可以做到。C語言可以編寫伺服器端軟體如Apache、Nginx,或者編寫GUI程式,如GTK。大多數程式語言的第一版是通過C語言實現,藉助前面提到的“一次編寫處處編譯”,最大的保證了這些程式語言的可移植性。在Web開發領域,C語言的應用相對較少,這也是一種取捨的結果,Web開發需要使用PHP、Ruby、Python這樣的動態語言,可以快速上線快速修改,可以最大程度滿足使用者時時變化的需求,這也是C語言的弱項。如果把程式語言的應用領域從硬體到管理軟體、Web程式做一個很粗略從下到上的排列,C語言適合領域是比較底層靠近硬體的部分,而新興語言比較偏重於高層管理或者Web開發這種相對貼近終端使用者的領域。比較流行的混合開發模式是使用C語言編寫底層高效能部分程式碼或後臺伺服器程式碼,而使用動態語言如Python做前端開發,充分發揮它們各自的優勢力量。

提到C語言的缺點,常常是它缺少這種或者那種特性,比如有人建議加入GC,有人建議加入並行或者併發支援,有人提到沒有一個比較完整的類似C++的異常策略。這些特性有的可以通過引入第三方庫來實現,但C語言的設計哲學其實決定了它不會像C++那樣“非常強大”。即使引入了某些人期望的特性,依然會是某些人喜歡某些人不喜歡的情形,現在的功能對於C語言應用領域來說已經夠用,其它特性可以通過特定程式語言實現,並且通過C API與C語言編寫的程式進行互動。任何一個工匠都不可能只使用一個工具完成他的工作,不同工具結合起來才能更快更好的完成任務。

提到C API,也稍微介紹一下,我們知道windows作業系統的api也好,Linux的系統api也好,或者是想給Ruby、Python編寫擴充套件模組,C語言形式的函式定義都是唯一的選擇。C語言就好像是一箇中間層或者是膠水,如果想把不同程式語言實現的功能模組混合使用,C語言是最佳的選擇。

提了這麼多關於C語言的好處,那麼學習C語言是否適合就看你自己的判斷了,例如要進行一個嵌入式專案,或者需要進行伺服器端開發,或者寫一個性能相關的元件等等,C語言都是比較好用的選擇。另外也可以在C++的使用過程中有意的使用C語言的思考方式,汲取C語言簡潔明快清晰地設計思路,對程式設計設計水平會有很大的提高。

C語言學習方法

在前面http://sunxiunan.com/?p=1597 曾經提到過一個比較系統學習一門新的程式語言的方式,C語言學習也可以按照類似的順序:閱讀參考書,閱讀程式碼,編寫除錯實際程式,上網參與討論,研究高階話題。

學習語言的開始一般是閱讀參考書。我建議選擇幾本非常經典的好書,仔細完整反覆閱讀幾遍,“書讀百遍其義自現”。選擇C語言學習的好處是,這幾本書基本上完整涵蓋了C語言程式設計領域的方方面面,不會像C++那樣,即使讀完一堆書還是有些糊塗,依然有這樣那樣難懂的陷阱。

1,參考書籍

在下面簡單點評一下,閱讀順序最好參照列出的順序。

image

如果你只想買一本書學習C語言,只需要買這一本就夠了。如果你經費足夠,建議你多買幾本,辦公室、家裡都放上一本,隨手都可以翻翻。用三個詞語來形容它就是:經典!經典!經典!這本薄薄的只有二百多頁的小書涵蓋了C語言的方方面面,前無古人而且後無來者,任何溢美之詞都不足以形容它。

《The C Programming Language》(後面稱為 K&R)裡面包含了一個簡單的語法解析器,包含了malloc如何實現,包含了一個完整的作業系統目錄瀏覽程式,這些程式的實用性極高,可以這樣說,如果學習任何一門語言能夠自己獨立動手實現以上的功能,基本上就可以算是入門了。K&R書裡面每段都蘊含著非常值得探究的軟體開發工程實踐經驗,如果沒有一定的開發經驗,其實是看不出來這些冰山下面的內容的,比如開頭一章就提出用寫完整程式碼這種方式來教學,而在書中那些C語言的陷阱或者可能出問題的地方,都有提到,但是由於篇幅所限,寫的非常簡約,很難讓人一下就看懂。我正在完整的逐字逐句的閱讀此書,希望能稍作註解,寫幾篇部落格分享一下。

這是K&R的中文譯本,可以先從中文譯本看起,然後再讀一遍英文原版,既可以學習英文,又可以體會原文那種簡約優美的風格。

這兩本書也是學習及使用C語言的朋友必備的兩本書,比如《C專家程式設計》,專門用兩三個章節詳細介紹C語言中陣列與指標的不同之處,這兩本書在某種程度上算是對K&R略過的地方做了詳細補充,強烈推薦。

這是最後一本強烈推薦你最好買回家作為案頭書必備的參考書。前面幾本書或者稍顯簡略,或者專注某個特定專題,都不適合遇到問題時翻查。這本《C語言參考手冊》可以看作是C語言程式設計的《新華字典》,全面而權威。裡面還涵蓋了C99的內容,緊跟時代潮流。

下面幾本書都可以作為交叉參考,也都很有價值,也是建議大家都買下來,好書如朋友,日久彌新,像是我推薦的這幾本書在douban或者amazon上評分都非常高,而且反覆再版。

指標的重要性如何,學過C語言(或者C++)的朋友都知道,這本書更是把指標拔高到了與C語言平起平坐的地位,其實也是從頭開始介紹,作為教學參考書也是可以的。

這本書是專門介紹C語言的標準庫如何實現的,比如malloc演算法,用標準的C語言該如何寫?strlen這個函式應該如何實現?儘管書中不少程式碼與真實的C標準庫相差很多(由於標準庫需要考慮效能優化,很多函式有一些特定的trick),但是絕對值得參考。

這本書其實就是C-FAQ的印刷版本,C-FAQ在各種程式語言的FAQ中可以稱得上質量一流。如果你想應聘或者招聘C語言相關程式設計師,這本書一定要參考。

這本書是基於特定作業系統Linux來介紹C語言程式設計,可作為計算機相關專業的教科書或入門參考書,也是書單裡面唯一一本國人原創的程式設計書籍,非常難得。書中幾乎所有內容都在網上直接公開,針對讀者的意見進行修改,這也是非常難得的一種開放態度。非常推薦大家買一本。

學習C語言,一定不能只讀書,應該動手練習完成書裡面的專案需求(比如編寫一個目錄瀏覽器)以及每章的練習題目。這就需要有可以實驗的環境,下面針對不同作業系統簡單做一下介紹。

2,動手實驗環境搭建

也沒有調查過,不知道現在學校裡學習C語言是不是依然跟著譚浩強老師用TurboC2.0程式設計,如果還是這個組合的話,那就太差勁了,趕快拋開它們。

下面主要介紹不同作業系統平臺下的整合程式設計環境,基於初學者以及我個人喜好,就不推薦大家命令列下用vim程式設計了,直接上IDE。

Windows系統下推薦大家使用Code::blocks這個軟體。這個軟體最大優點是自帶了基於mingw的GCC以及GDB,只要下載70M左右軟體包,就可以完整支援C++、C語言程式設計了。各種功能(比如除錯功能)也很強大,版本更新也比較快。注意下載選擇名字有mingw的檔案,比如最新版本是codeblocks-10.05mingw-setup.exe(版本也許有所不同)。

image

另外推薦codelite,相比codeblock,這個更新的更頻繁一些。也支援各種比較有用的外掛、除錯特性、WX等等。

如果需要做Windows作業系統的開發,可以下載Visual C++ 2010 Express。

image

因為Code::Blocks不包含Windows程式設計標頭檔案(實際是因為沒有Windows SDK),無法編寫Windows作業系統相關的介面應用程式或者服務類程式。而VC++Express自帶了這些標頭檔案以及程式設計庫,雖然功能稍微簡陋,但對於練習使用基本夠用。

對於計算機專業的學生朋友,建議大家使用Linux作業系統,或者更詳細一點是使用Xubuntu作業系統作為桌面,使用Netbeans和GCC這個組合(當然也可以選擇Code::Blocks)。在Xubuntu下可以通過apt-get install build-essential這個命令安裝gcc相關程式,已經可以在Terminal下編譯C語言程式了,但為了使用方便,大家可以選擇Netbeans的C++支援包,在Netbeans網站上就能下載。

image

如果使用蘋果Mac系統,毫無疑問XCode就是程式設計的絕佳選擇,XCode可以在蘋果開發者網站上免費下載,在IPhone SDK中也包含了XCode。

image

如果手頭沒有合適的程式設計環境,還需要實驗一些簡單的程式碼,可以用http://codepad.org/ 提供的服務,線上編寫執行程式碼。

image

另外建議大家申請一個github.com的賬號,在gist.github.com可以儲存自己的練習程式碼,就不需要隨身帶著U盤了。

3,網路資源

從維基百科可以看到,C語言1972年由Dennis Ritchie設計的命令式、結構化正規化程式語言。型別為靜態的弱型別,需要顯式定義。最新國際標準為C99。設計上主要受到了B、ALGOL68、組合語言、PL/I、FORTRAN的影響,C語言也影響了大量程式語言,如C++、Objective-C、C#、Java、Go、PHP、Python等等(個人覺得受C影響很大的是PHP,基本上有C程式設計基礎的程式設計師,很容易就能上手PHP了,除了PHP的OO部分)。

在維基百科條目中有很大篇幅介紹了作者認為C語言缺失的特性,比如面向物件、多執行緒、GC、異常處理等等,當然這有些吹毛求疵,如果需要這些特性,完全可以用其它程式語言。另外一個介紹的重點是“未定義行為”,有些我們認為理所當然的結果,其實在C語言標準中並沒有明確定義,假定這些行為應該如何,當程式使用另外的編譯器或者不同版本編譯器編譯執行,都可能有bug產生。

接下來維基百科條目談到了C語言的用處,必須承認儘管現在程式語言成百上千,能稱之為“系統級”的少之又少,新興語言中只有Go還能稱得上。現在大規模軟體專案中完全選用C語言可能性不大,但是核心部分完全可以用C搭建,相對C++開發工具的高昂價格,C語言相關的免費輔助開發軟體非常豐富,比如splint,valgrind,不少核心庫經過長期使用也都非常穩定。

由於C語言廣泛支援各種平臺以及編譯器相對成熟可靠,不少程式語言選擇C語言作為一箇中間層,比如Glasgow Haskell編譯器就是這樣做的。

另一個可以找到大量C語言程式設計相關資料的地方是“美味書籤”,通過搜尋特定關鍵字 (C + programming)就可以找到很多值得挖掘的資源http://delicious.com/search?p=c+programming

程式設計師往往是懶惰的,“拿來主義”、“拷貝主義”很流行也很有效,當對某個函式或者關鍵字不是很理解的時候,看看別人是怎麼使用的,會非常有啟發性。這裡介紹幾個常用的程式碼搜尋網站,最常用的是google的codesearch,可惜已經關閉。還可以選擇 http://koders.com/ http://www.krugle.org/ http://www.codase.com/ 。另外可以參考維基百科上一個“帶有C語言示例的文章”分類,裡面程式碼寫的也很不錯。還可以在github.com上搜索相關專案。在前面部落格文章我還介紹了一個名為羅塞塔程式碼的網站http://rosettacode.org/ 這個網站上可以找到不同程式語言針對某個問題的解決方案,用於學習比較非常便利。

學習程式設計也需要大量閱讀名家經典程式碼,與學中文英文需要大量閱讀名著一個道理,C語言程式設計優質專案那是“彩旗飄舞,人山人海”,個人建議可以看看Lua、Sqlite、Nginx這些專案的程式碼,程式碼量不多,而且程式碼質量也都比較高。另外可以看看Linux核心程式碼,坊間有不少書籍可以幫助解讀。關於如何很好的閱讀程式碼,大家可以參考《程式碼閱讀 Code Reading》這本書。

書看了幾本,程式碼寫了一些,也略微讀了讀其他人的程式碼,就應該用C語言來完成真實工作中碰到的問題,讓C語言真正成為你的瑞士軍刀。只有當你經常使用C語言來進行程式設計工作,經常思考如何通過C設計一個優雅高效的系統,才能更深刻的理解C語言設計哲學。

C語言學習當中,有一些難點需要多加註意,如pointer與array的不同之處,複雜型別定義如何解讀,如何正確使用預處理preprocessor以及巨集定義。其實這些內容在前面書籍都是反覆提到,如果按部就班學習下來,應該不成問題。

當C語言學習的差不多時候,還可以學習一門動態語言,比如Lua或者Python,試著在實際工作專案中混合使用動態語言與C語言,一加一發揮出來的力量不僅僅是二,而是非常二(說笑一下,哈哈)。

還有什麼問題,歡迎留言。

附錄

一些有用的C語言網路資源:

Dan Saks在embedded.com上的專欄Programming Pointer ,裡面文章很有深度,值得一讀。

comp.lang.c以及c.moderated這兩個討論組推薦訂閱,相當於網際網路最大的C相關程式設計問題論壇:

一些值得關注及研究的C語言相關專案:

一些C語言程式設計時可以使用的工具軟體,幫你提高程式碼質量:

C語言程式設計規範程式設計標準:

C語言程式設計電子書及教程:

《C語言深度解剖》這本可以在百度文庫或google搜到,可以讀讀,有些參考性。

《C標準和實現》作者姚新顏,他的《深度探索C、C++》算是當年比較有深度的書籍,可惜已經絕版了。這本書也可以在百度文庫搜到。這本書也比較值得讀。