《linuxC編程一站式學習》是2009年電子工業出版社出版的圖書,作者是北京亞嵌教育研究中心、宋勁杉。
基本介紹
- 書名:linuxC編程一站式學習
- 作者:北京亞嵌教育研究中心 宋勁杉 編著
- ISBN:978-7-121-09771-3
- 頁數:480頁
- 定價:60.00元
- 出版社:電子工業出版社
- 出版時間:2009年11月
- 開本:16開
適用人群,前 言,目 錄,
適用人群
本書適合做零基礎的初學者學習C語言的第一本教材,幫助讀者打下牢固的基礎。有一定的編程經驗但知識體系不夠完整的讀者也可以對照本書查缺補漏,從而更深入地理解程式的工作原理。本書最初是為北京亞嵌教育研究中心的嵌入式Linux系統工程師就業班課程量身定做的教材之一,也適合作為高等院校程式設計基礎課程的教材。本書對於C語言的語法介紹得非常全面,對C99標準做了很多解讀,因此也可以作為一本精簡的C語言語法參考書。
本書有兩條線索,一條線索是以Linux平台為載體全面深入地介紹C語言的語法和程式的工作原理,另一條線索是介紹程式設計的基本思想和開發調試方法。本書分為兩部分:第一部分講解程式語言和程式設計的基本思想方法;第二部分結合作業系統和體系結構的知識講解程式的工作原理。
前 言
本書最初是為北京亞嵌教育研究中心的嵌入式Linux系統工程師就業班課程量身定做的教材之一。該課程是為期四個月的全日制職業培訓,要求學員畢業時具備非常Solid的C語言編程能力,能熟練地使用Linux系統,同時對計算機體系結構與指令集、作業系統原理和設備驅動程式都有比較深入的了解。然而學員入學時的水平是非常初級而且參差不齊的:學歷有專科、本科也有研究生;專業有和計算機相關的,也有很不相關的(例如會計專業);以前從事的職業有和技術相關的也有完全不相關的(例如HR);年齡從二十歲出頭到三十五六歲的都有。這么多背景、基礎、思維習慣和理解能力完全不同的人來聽同一堂課,大家都迫切希望學會嵌入式開發技術,投身IT行業,這就是職業教育的特點,也是我編寫本書時需要考慮的主要問題。
學習編程絕不是一件簡單的事,尤其是對於零基礎的初學者來說。大學的計算機專業有四年時間從零基礎開始培養一個人,微積分、線性代數、機率論、離散數學、組合數學、自動機、編譯原理、作業系統、計算機組成原理等一堆基礎課,再加上C/C++、Java、資料庫、網路工程、軟體工程、計算機圖形學等一堆專業課,最後培養出一個能找到工作的學生。很遺憾這最後一條很多學校沒有做好,據我們考查,來亞嵌培訓的很多學生基礎幾乎為零,我不知道為什麼。與之形成鮮明對比的是,只給我們四個月的時間,同樣要求從零基礎開始,最後培養出一個能找到工作的學生,而且還要保證他找到好工作,這就是職業教育的特點。
為什麼我說“只給我們四個月的時間”?我們倒是想教四年呢,但學時的長短我們做不了主,是由市場規律決定的。四年的任務要求四個月做好,要怎么完成這樣一個幾乎不可能的任務呢?有些職業教育給出的答案是“實用主義”,打出了“有用就學,沒有用就不學”的口號,大肆貶低說大學裡教的基礎課都是過時的、無用的,只有他們教的技術才是實用的。這種炒作很不好,我認為大學裡教的每一門課都是非常有用的,基礎知識在任何時候都不會過時,倒是那些時髦的“實用技術”有可能很快就會過時了。
四年的任務怎么才能用四個月做好?我們給出的答案是“最佳化”。現在大學裡安排的課程體系最大的缺點就是根本不考慮最佳化。每個過來人都會有這樣的感覺:大一大二學了好多數學課,卻不知道都是乾什麼用的,不明白為什麼要學。連它有什麼用都不知道怎么能有興趣學好呢?到大三大四學專業課時,用到以前的知識了,才發現以前學的數學是多么有用,然而早就忘得一乾二淨了,考完試都還給老師了。回頭重新學,才發現很多東西以前根本沒學明白,現在真的學明白了,那么前兩年的時間豈不是都浪費了?大學裡的課程體系還有一個缺點就是不靈活,每門課必須占用一個學期,必須由一個老師教,不同課程的老師之間沒有任何溝通和銜接,其實這些課程之間是相互依賴的,把它們強行拆開是不符合人的認知規律的。比如我剛上大學的時候,大一上半學期就被逼著學習C語言,其實C語言是一門很難的程式語言,不懂編譯原理、作業系統和計算機體系結構根本不可能學明白,那半個學期自然就浪費掉了。當時幾乎所有學校的計算機相關專業都是這樣,大一剛來就學C語言,有的學校更瘋狂,上來就學C++,導致大多數學生都以為自己會C語言,但其實都是半吊子水平,到真正寫代碼的時候經常為一個Bug搞得焦頭爛額,卻沒有機會再系統地學一遍C語言。因為在學校看來,C語言早在大一就給你“上完了”,就像一頓飯已經吃完了,不管你吃飽沒吃飽,不會再讓你重吃一遍了。顯而易見,如果要認真地對這些課程進行最佳化,的確是有很多水分可以擠的。
本書有什麼特點
強調基本概念和基本原理,在編排順序上重視概念之間的依賴關係,每次引入一個新的概念,只依賴於前面章節已經講過的概念,而絕不會依賴於後面章節要講的概念。有些地方為了敘述得完整,也會引用後面要講的內容,比如說“有關××我們到第×章再仔細講解”,凡是這種引用都不是必要的依賴,可以當它不存在,只管繼續往下學習就行了。
儘量做到每個知識點直到要用的時候才引入。過早引入一個知識點,講完了又不用它,讀者很快就會遺忘,這是不符合認知規律的。
本書面向什麼樣的讀者
這是一本從零基礎開始學習編程的書,不要求讀者有任何編程經驗,但讀者至少需要具備以下素質:
熟悉Linux系統的基本操作。如果不具備這一點,請先參考其他教材學習相關知識,熟練之後再學習本書,《鳥哥的Linux私房菜》據說是Linux系統管理和套用方面比較好的一本書。但學習本書並不需要會很多系統管理技術,只要會用基本命令、會自己安裝系統和軟體包就足夠了。
具有高中畢業的數學水平。本書會用到高中的數學知識。事實上,如果不具有高中畢業的數學水平,也不必考慮做程式設計師了。但並不是說只要具有高中畢業的數學水平就足夠做程式設計師了,只能說看這本書應該沒有問題,數學是程式設計師最重要的修養,計算機科學其實就是數學的一個分支,如果你的數學功底很差,日後還需要惡補一下。
具有高中畢業的英文水平。理由同上。
對計算機的原理和本質深感興趣,不是為就業而學習,不是為拿高薪而學習,而是真的感興趣,想把一切來龍去脈搞得清清楚楚而學習。
勤于思考。本書盡最大努力理清概念之間的依賴關係,力求一站式學習,讀者不需要為了找一個概念的定義去翻閱其他書籍,也不需要為了搞清楚一個概念在本書中亂翻一通,只需要從前到後按順序學習即可。但一站式學習並不等於傻瓜式學習,有些章節有一定的難度,需要讀者積極思考才能領會。本書可以替你節省時間,但不能替你思考,不要指望像看小說一樣走馬觀花看一遍就能學會。
為什麼要學這本書而不是K&R
《The C Programming Language》(後文簡稱[K&R])是公認的世界上最經典的C語言教程之一,這點毫無疑問。在C標準出台之前,K&R第一版就是事實上的C標準。C89標準出台之後,K&R跟著推出了第二版,可惜此後就沒有更新過了,所以不能反映C89之後C語言的發展以及最新的C99標準。本書在這方面做了很多補充。本書與其說是講C語言,不如說是以C語言為載體講計算機和作業系統的原理,而K&R只是為了講C語言而講C語言,側重點不同,內容編排也很不相同。K&R寫得非常好,代碼和語言都非常簡潔,但很可惜,只有會C語言的人才懂得欣賞它,K&R是非常不適合入門學習的,尤其不適合零基礎的學生學習。
本書“是什麼”和“不是什麼”
本書包括兩大部分:
C語言入門。介紹基本的C語法,幫助沒有任何編程經驗的讀者理解什麼是程式以及怎么寫程式,培養程式設計師的思維習慣,找到編程的感覺。前半部分改編自《How To Think Like A Computer Scientist: Learning with C++》(後文簡稱[ThinkCpp])。
C語言本質。結合計算機和作業系統的原理講解C程式是怎么編譯、連結、運行的,同時全面介紹C的語法。位運算的章節改編自林小竹老師的講義;鍊表和二叉樹的章節改編自朱仲濤老師的講義;彙編語言的章節改編自《Programming from the Ground Up: An Introduction to Programming using Linux Assembly Language》(後文簡稱[GroundUp]),在該書的最後一章中提到,學習編程有兩種Approach,一種是“Bottom Up”,一種是“Top Down”,它們各有優缺點,而我們需要將兩者結合起來。所以我編寫本書的思路是:第一部分Top Down;第二部分Bottom Up;第三部分可以算填補了中間的空隙,三部分全都圍繞C語言展開。
這本書定位在入門級,雖然內容很多,但不是一本百科全書,除了C語言的基礎知識要講透之外其他內容都不深入,書中列出了很多參考資料,是讀者進一步學習的起點。[K&R]的第1章是一個Whirlwind Tour,把全書的內容簡單概括了一遍,然後再逐個深入講解。本書也可以看作是計算機專業課程體系的一個Whirlwind Tour,學習完本書之後讀者有了一個全局觀,再去學習那些參考資料就應該很容易上手了。
為什麼要在Linux平台上學C語言?
用Windows學C語言不好嗎?
用Windows還真的是學不好C語言。C語言是一種面向底層的程式語言,要寫好C程式,必須對作業系統的工作原理非常清楚,因為作業系統也是用C語言編寫的,我們用C語言編寫應用程式可以直接使用作業系統提供的接口。既然你選擇了本書,你一定了解:Linux是一種開源的作業系統,你有任何疑問都可以從原始碼和文檔中找到答案,即使你看不懂原始碼,也找不到文檔,也很容易找個高手教你,各種郵件列表、新聞組和論壇上從來都不缺樂於助人的高手;而Windows是一種封閉的作業系統,除了微軟的員工別人都看不到它的原始碼,只能通過文檔去猜測它的工作原理。更糟糕的是,微軟向來喜歡藏著掖著,好用的功能留著自己用,而不會寫到文檔里公開。本書的第一部分在Linux或Windows平台上學習都可以,但第二部分和第三部分介紹了很多Linux作業系統的原理以幫助讀者更深入地理解C語言,所以後兩部分只能在Linux平台上學習。
Windows平台上的開發工具往往和各種集成開發環境(Integrated Development Environment,IDE)綁在一起,例如Visual Studio、Eclipse等。使用IDE確實很便捷,但IDE對於初學者絕對不是好東西。微軟喜歡宣揚傻瓜式編程的理念,告訴你用滑鼠拖幾個控制項,然後單擊一個按鈕就可以編譯出程式來,但是真正有用的程式有哪個是這么拖出來的?很多從Windows平台入門學編程的人,編了好幾年程式,還是只知道編完程式單擊一個按鈕就完事了,把幾個源檔案拖到一個項目里就可以編譯到一起了,如果有更複雜的需求他們就傻眼了,因為他們腦子裡只有按鈕、選單的概念,根本沒有編譯器、連結器、Makefile的概念,甚至連命令行都沒用過,然而這些都是初學編程就應該建立起來的基本概念。另一方面,編譯器、連結器和C語言的語法有著密切的關係,不了解編譯器、連結器的工作原理,也不可能真正掌握C語言的語法。所以,IDE並沒有幫助你學習,而是阻礙了你的學習,本來要學好C編程只要把語法和編譯命令學會就行了,現在有了IDE,除了學會語法和編譯命令,你還得弄清楚編譯命令和IDE是怎么集成的,這才算學明白了,本來就很複雜的學習任務被IDE搞得更加複雜了。Linux用戶的使用習慣從來都是以敲命令為主,以滑鼠操作為輔,從學編程的第一天起就要敲命令編譯程式,等到你把這些基本概念都搞清楚了,你覺得哪個IDE好用你再去用,不過到那時候你可能會更喜歡vi或emacs而不是IDE了。
體例說明
像The quick brown fox jumps over the lazy dog這樣的字型在本書中是代碼字型。這種字型的名稱是Dejavu Sans Mono,為什麼我要提倡用這種字型呢?第一,它是等寬字型,因此適合做代碼字型。第二,它的1和l、0和O區分得非常清楚(我在教學中發現初學者很容易把這些字元抄錯),因此它比Courier New更適合做代碼字型。第三, 它是我的Linux圖形終端的默認字型,採用這種字型排版可以使得看書和看螢幕的感覺很一致,希望讀者在看這本書時也會有這種Dejavu(似曾相識)的感覺。
像下面這樣有邊線的是代碼:
#! /bin/sh
VAR=1
VAR=$(($VAR+1))
echo $VAR
沒有邊線的是終端顯示,包括輸入的命令和程式運行結果,例如:
$ VAR=1
$ VAR=$(($VAR+1))
$ echo $VAR
2
本書中統一用$表示Shell提示符。
加粗的字句表示強調。
在定義一個名詞時會給出它的英文名稱,例如集成開發環境(Integrated Development Environment,IDE),通過書後的索引可以找到這些定義在書中首次出現的位置。
致謝
本書的寫作得到了北京亞嵌教育研究中心的全力支持,尤其感謝李明老師和何家勝老師。沒有公司的支持,我不可能有時間有條件寫這本書,也不可能有機會將這本書公開在網上。
然後要感謝亞嵌教育的歷屆學員和各位老師,在教學和討論的過程中我經常會得到有益的啟發,這些都促使本書更加完善。在本書的寫作過程中,很多讀者為本書提出了很有價值的建議,很多建議是熱心網友通過線上評論提出的,有些網友我只知道ID或E-mail。在此向他們表示感謝。
感謝幫助過我的老師們:李明、何家勝、邸海霞、郎鐵山、朱仲濤、廖文江、韓超、秦蔚、吳岳、張 、邢文鵬、何曉龍、林小竹、衛劍釩、郭同彬、王波、王磊。
感謝熱心網友:ddd、wuyulei、commapopo、田偉、田雨、daidai、鄧楠、杜朴風、Zoom.Quiet、陳莉君老師、楊景、章鈺、chen、Jiawei Zhang、waterloo、張現超、曾宇、董俊波、RobinXiang、劉艷明、been2100、cleverd、juicerococo、徐斌、cyy、Linux_Xfce、馮海雲、侯延祥、churchmice、codycody23、syfeagle、王公僕、劉敏、Laciq、yuchen、陸楊、陳楊希、love_wc3、姚磊、芝麻、wadenx、沈震、sunbingfly、mick、baaluck、曹帥軍、zhoudy、朱夜光、刺蝟、leezhenfeng、王兆宏、徐凱、碼匠、況海斌、尹志偉、王星。
還要感謝電子工業出版社博文視點資訊有限公司的周筠老師和李冰老師的大力支持,感謝江立編輯嚴謹細緻的工作。
在寫作過程中我遇到過很多困難:工作繁忙、對未來迷茫、生活壓力大、缺乏安全感、個人瑣事等。然而有這么多熱心的同學、老師、朋友、網友在等著閱讀我的書線上更新的內容,給我提建議,希望我把書改得更完善,這是我堅持寫下去的最大動力。謝謝你們!
由於作者水平十分有限,沒寫過C編譯器和C標準庫,所以疏漏之處在所難免,如有錯誤歡迎廣大讀者朋友批評指正。寫書是一件嚴肅的事,書中的錯誤所有人都看得見,白紙黑字賴不掉的。我教過的很多學生都在大學裡學過C語言,甚至考過二級,但程式寫得一塌糊塗,連最基本的概念都搞錯了,以前學過的C語言教材中的錯誤在他們腦子裡根深蒂固,即使我糾正多次,他們仍然只記得以前學過的錯誤概念。這種有基礎的學生還不如沒有任何基礎的學生教起來容易。我非常害怕我教給別人的知識也是錯的,所以我仔細研究了C99之後才敢動筆寫書。這本書涵蓋的話題比較廣泛,我竭盡全力也不足以保證書中的內容全部正確,還要依靠社區的力量一起來完善這本書,這樣才能真正對讀者負責,所以我選擇將這本書開源。。
希望本書能成為你求學道路上的第一個夥伴。
宋勁杉
2009年7月22日
目 錄
上篇 C語言入門
第1章 程式的基本概念 2
1.1 程式和程式語言 2
1.2 自然語言和形式語言 6
1.3 程式的調試 7
1.4 第一個程式 9
第2章 常量、變數和表達式 12
2.1 繼續Hello World 12
2.2 常量 15
2.3 變數 16
2.4 賦值 18
2.5 表達式 19
2.6 字元類型與字元編碼 23
第3章 簡單函式 24
3.1 數學函式 24
3.2 自定義函式 26
3.3 形參和實參 31
3.4 全局變數、局部變數和作用域 35
第4章 分支語句 41
4.1 if語句 41
4.2 if/else語句 43
4.3 布爾代數 45
4.4 switch語句 49
第5章 深入理解函式 51
5.1 return語句 51
5.2 增量式開發 54
5.3 遞歸 58
第6章 循環語句 64
6.1 while語句 64
6.2 do/while語句 66
6.3 for語句 67
6.4 break和continue語句 69
6.5 嵌套循環 70
6.6 goto語句和標號 71
第7章 結構體 74
7.1 複合類型與結構體 74
7.2 數據抽象 78
7.3 數據類型標誌 82
7.4 嵌套結構體 84
第8章 數組 85
8.1 數組的基本概念 85
8.2 數組套用實例:統計隨機數 88
8.3 數組套用實例:直方圖 91
8.4 字元串 94
8.5 多維數組 95
第9章 編碼風格 100
9.1 縮進和空白 100
9.2 注釋 104
9.3 標識符命名 107
9.4 函式 108
9.5 indent工具 108
第10章 gdb 110
10.1 單步執行和跟蹤函式調用 110
10.2 斷點 117
10.3 觀察點 121
10.4 段錯誤 125
第11章 排序與查找 128
11.1 算法的概念 128
11.2 插入排序 129
11.3 算法的時間複雜度分析 131
11.4 歸併排序 133
11.5 線性查找 138
11.6 折半查找 139
第12章 棧與佇列 144
12.1 數據結構的概念 144
12.2 堆疊 144
12.3 深度優先搜尋 146
12.4 佇列與廣度優先搜尋 152
12.5 環形佇列 156
本階段總結 159
下篇 C語言本質
第13章 計算機中數的表示 162
13.1 為什麼計算機用二進制計數 162
13.2 不同進制之間的換算 164
13.3 整數的加減運算 165
13.3.1 Sign and Magnitude表示法 165
13.3.2 1's Complement表示法 166
13.3.3 2's Complement表示法 167
13.3.4 有符號數和無符號數 168
13.4 浮點數 169
第14章 數據類型詳解 172
14.1 整型 172
14.2 浮點型 176
14.3 類型轉換 177
14.3.1 Integer Promotion 177
14.3.2 Usual Arithmetic Conversion 178
14.3.3 由賦值產生的類型轉換 179
14.3.4 強制類型轉換 179
14.3.5 編譯器如何處理類型轉換 179
第15章 運算符詳解 182
15.1 位運算 182
15.1.1 按位與、或、異或、取反運算 182
15.1.2 移位運算 183
15.1.3 掩碼 184
15.1.4 異或運算的一些特性 185
15.2 其他運算符 186
15.2.1 複合賦值運算符 186
15.2.2 條件運算符 186
15.2.3 逗號運算符 187
15.2.4 sizeof運算符與typedef類型聲明 187
15.3 Side Effect與Sequence Point 189
15.4 運算符總結 191
第16章 計算機體系結構基礎 193
16.1 記憶體與地址 193
16.2 CPU 193
16.3 設備 196
16.4 MMU 198
16.5 Memory Hierarchy 201
第17章 x86彙編程式基礎 205
17.1 最簡單的彙編程式 205
17.2 x86的暫存器 208
17.3 第二個彙編程式 209
17.4 定址方式 211
17.5 ELF檔案 212
17.5.1 目標檔案 213
17.5.2 執行檔 218
第18章 彙編與C之間的關係 224
18.1 函式調用 224
18.2 main函式、啟動例程和退出狀態 230
18.3 變數的存儲布局 237
18.4 結構體和聯合體 244
18.5 C內聯彙編 248
18.6 volatile限定符 250
第19章 連結詳解 255
19.1 多目標檔案的連結 255
19.2 定義和聲明 260
19.2.1 extern和static關鍵字 260
19.2.2 頭檔案 264
19.2.3 定義和聲明的詳細規則 268
19.3 靜態庫 271
19.4 共享庫 274
19.4.1 編譯、連結、運行 274
19.4.2 函式的動態連結過程 281
19.4.3 共享庫的命名慣例 282
19.5 虛擬記憶體管理 284
第20章 預處理 290
20.1 預處理的步驟 290
20.2 宏定義 291
20.2.1 函式式宏定義 291
20.2.2 內聯函式 294
20.2.3 #、##運算符和可變參數 296
20.2.4 #undef預處理指示 298
20.2.5 宏展開的步驟 299
20.3 條件預處理指示 300
20.4 其他預處理特性 303
第21章 Makefile基礎 306
21.1 基本規則 306
21.2 隱含規則和模式規則 313
21.3 變數 317
21.4 自動處理頭檔案的依賴關係 321
21.5 常用的make命令行選項 324
第22章 指針 327
22.1 指針的基本概念 327
22.2 指針類型的參數和返回值 331
22.3 指針與數組 332
22.4 指針與const限定符 335
22.5 指針與結構體 337
22.6 指向指針的指針與指針數組 337
22.7 指向數組的指針與多維數組 340
22.8 函式類型和函式指針類型 341
22.9 不完全類型和複雜聲明 344
第23章 函式接口 349
23.1 本章的預備知識 349
23.1.1 strcpy與strncpy 349
23.1.2 malloc與free 354
23.2 傳入參數與傳出參數 358
23.3 兩層指針的參數 360
23.4 返回值是指針的情況 362
23.5 回調函式 365
23.6 可變參數 368
第24章 C標準庫 372
24.1 字元串操作函式 373
24.1.1 給字元串賦初值 373
24.1.2 取字元串的長度 374
24.1.3 拷貝字元串 375
24.1.4 連線字元串 377
24.1.5 比較字元串 378
24.1.6 搜尋字元串 379
24.1.7 分割字元串 380
24.2 標準I/O庫函式 383
24.2.1 檔案的基本概念 383
24.2.2 fopen/fclose 384
24.2.3 stdin/stdout/stderr 387
24.2.4 errno與perror/strerror函式 388
24.2.5 以位元組為單位的I/O函式 391
24.2.6 操作讀寫位置的函式 393
24.2.7 以字元串為單位的I/O函式 395
24.2.8 以記錄為單位的I/O函式 397
24.2.9 格式化I/O函式 399
24.2.10 C標準庫的I/O緩衝區 406
24.2.11 本節綜合練習 410
24.3 數值字元串轉換函式 412
24.4 分配記憶體的函式 414
第25章 鍊表、二叉樹和哈希表 415
25.1 鍊表 415
25.1.1 單鍊表 415
25.1.2 雙向鍊表 421
25.1.3 靜態鍊表 425
25.1.4 本節綜合練習 426
25.2 二叉樹 426
25.2.1 二叉樹的基本概念 426
25.2.2 排序二叉樹 432
25.3 哈希表 437
本階段總結 439
附錄A 字元編碼 442
索引 449
參考書目 474