關(guān)于我們
書單推薦
新書推薦
|
嵌入式Linux與物聯(lián)網(wǎng)軟件開發(fā) C語言內(nèi)核深度解析
本書的原型思想和內(nèi)容,發(fā)源于朱有鵬老師早些年的研發(fā)和學(xué)習經(jīng)歷,發(fā)展于后來數(shù)年的線下培訓(xùn)授課經(jīng)歷,并成熟于視頻課程《C語言高級專題》(隸屬于《朱有鵬老師嵌入式Linux核心課程》系列視頻課程的第4部分)。本書正是基于這套視頻課程的課件整理而來,參與各章節(jié)整理和編寫的都是學(xué)習了視頻課程的學(xué)生,由朱有鵬老師和張先鳳老師檢驗并完善成書。這些參與編寫的同學(xué)有的已經(jīng)工作數(shù)年、有的則尚未走出大學(xué)校園。選擇他們合作創(chuàng)作本書,就是為了告訴讀者:做技術(shù)并不要求你天賦異稟,只需要你感興趣、愿意去探索和練習,你也可以成功。
針對性強:面向嵌入式Linux內(nèi)核源碼、底層驅(qū)動軟件開發(fā)等技術(shù)方向。
精華原創(chuàng):凝結(jié)作者多年研發(fā)及教學(xué)經(jīng)驗,幫助讀者真正深度理解難點。 求職必讀:詳解常見面試題,完全應(yīng)對 “嵌入式軟件工程師”崗位需求。
朱有鵬,互聯(lián)網(wǎng)課程《朱老師物聯(lián)網(wǎng)大講堂》創(chuàng)始人、杰出講師;51CTO學(xué)院杰出講師、CSDN技術(shù)專家、國內(nèi)物聯(lián)網(wǎng)教育領(lǐng)域先驅(qū);具有大型企業(yè)級項目研發(fā)經(jīng)驗和豐富的教學(xué)經(jīng)驗。授課風趣幽默、條理清晰、通俗易懂,對知識有自己獨到見解。能舉一反三,發(fā)散學(xué)生的思維,指引學(xué)生發(fā)掘適合自己的學(xué)習方法。
張先鳳,《朱老師物聯(lián)網(wǎng)大講堂》聯(lián)合創(chuàng)始人、杰出講師;長期從事企業(yè)級物聯(lián)網(wǎng)項目研發(fā)和物聯(lián)網(wǎng)相關(guān)教學(xué)工作,對物聯(lián)網(wǎng)各關(guān)鍵環(huán)節(jié)技術(shù)均有所涉獵,對物聯(lián)網(wǎng)未來發(fā)展和教學(xué)有著獨特見解,立志長期扎根物聯(lián)網(wǎng)相關(guān)研發(fā)和教學(xué)工作。
第1 章 C 語言與內(nèi)存… ……………………………………………………………………… 1
1.1 引言………………………………………………………………………………………………… 1 1.2 計算機程序運行的目的…………………………………………………………………………… 1 1.2.1 什么是程序… …………………………………………………………………………………… 1 1.2.2 計算機運行程序的目的………………………………………………………………………… 1 1.2.3 靜態(tài)內(nèi)存SRAM 和動態(tài)內(nèi)存DRAM…………………………………………………………2 1.2.4 馮·諾伊曼結(jié)構(gòu)和哈佛結(jié)構(gòu)… ………………………………………………………………3 1.2.5 總結(jié):程序運行為什么需要內(nèi)存呢……………………………………………………………4 1.2.6 深入思考:如何管理內(nèi)存(無OS 時,有OS 時)… ………………………………………4 1.3 位、字節(jié)、半字、字的概念和內(nèi)存位寬………………………………………………………… 5 1.3.1 深入了解內(nèi)存(硬件和邏輯兩個角度)… ……………………………………………………5 1.3.2 內(nèi)存的邏輯抽象圖(內(nèi)存的編程模型)… ……………………………………………………6 1.3.3 位和字節(jié)…………………………………………………………………………………………7 1.3.4 字和半字…………………………………………………………………………………………7 1.3.5 內(nèi)存位寬(硬件和邏輯兩個角度)… …………………………………………………………7 1.4 內(nèi)存編址和尋址、內(nèi)存對齊……………………………………………………………………… 8 1.4.1 內(nèi)存編址方法… …………………………………………………………………………………8 1.4.2 關(guān)鍵:內(nèi)存編址是以字節(jié)為單位………………………………………………………………8 1.4.3 內(nèi)存和數(shù)據(jù)類型的關(guān)系…………………………………………………………………………9 1.4.4 內(nèi)存對齊……………………………………………………………………………………… 10 1.5 C語言如何操作內(nèi)存… …………………………………………………………………………… 10 1.5.1 C 語言對內(nèi)存地址的封裝…………………………………………………………………… 10 1.5.2 用指針來間接訪問內(nèi)存……………………………………………………………………… 11 1.5.3 指針類型的含義……………………………………………………………………………… 12 1.5.4 用數(shù)組來管理內(nèi)存…………………………………………………………………………… 12 1.6 內(nèi)存管理之結(jié)構(gòu)體………………………………………………………………………………… 14 1.6.1 數(shù)據(jù)結(jié)構(gòu)這門學(xué)問的意義… ………………………………………………………………… 14 1.6.2 最簡單的數(shù)據(jù)結(jié)構(gòu):數(shù)組…………………………………………………………………… 141 6.3 數(shù)組的優(yōu)缺點………………………………………………………………………………… 14 1.6.4 結(jié)構(gòu)體隆重登場……………………………………………………………………………… 14 1.6.5 題外話:結(jié)構(gòu)體內(nèi)嵌指針實現(xiàn)面向?qū)ο蟆?5 1.7 內(nèi)存管理之棧(stack)… ……………………………………………………………………… 15 1.7.1 什么是! …………………………………………………………………………………… 15 1.7.2 棧管理內(nèi)存的特點(小內(nèi)存、自動化)… ………………………………………………… 16 1.7.3 棧的應(yīng)用舉例:局部變量和函數(shù)調(diào)用……………………………………………………… 16 1.7.4 棧的約束(預(yù)定棧大小不靈活,怕溢出)… ……………………………………………… 17 1.8 內(nèi)存管理之堆……………………………………………………………………………………… 18 1.8.1 什么是堆… …………………………………………………………………………………… 18 1.8.2 堆管理內(nèi)存的特點(大塊內(nèi)存、手工分配/ 使用/ 釋放)………………………………… 18 1.8.3 C 語言操作堆內(nèi)存的接口(malloc/free)… ……………………………………………… 18 1.8.4 堆的優(yōu)勢和劣勢(管理大塊內(nèi)存、靈活、容易內(nèi)存泄漏)… …………………………… 19 1.8.5 靜態(tài)存儲區(qū)…………………………………………………………………………………… 19 課后題… ………………………………………………………………………………………………… 19 第2 章 C 語言位操作… ………………………………………………………………………21 2.1 引言………………………………………………………………………………………………… 21 2.2 常用位操作符……………………………………………………………………………………… 21 2.2.1 位與(&)……………………………………………………………………………………… 21 2.2.2 位或(|)… …………………………………………………………………………………… 22 2.2.3 位取反(~)…………………………………………………………………………………… 23 2.2.4 位異或(^)…………………………………………………………………………………… 24 2.2.5 左移位(<<)………………………………………………………………………………… 25 2.2.6 右移位(>>)………………………………………………………………………………… 26 2.3 位操作與寄存器…………………………………………………………………………………… 26 2.3.1 寄存器的操作………………………………………………………………………………… 26 2.3.2 寄存器特定位清零用&……………………………………………………………………… 27 2.3.3 寄存器特定位置1 用|… …………………………………………………………………… 27 2.3.4 寄存器特定位取反用~……………………………………………………………………… 27 2.4 位運算構(gòu)建特定二進制數(shù)………………………………………………………………………… 28 2.4.1 使用移位獲取特定位為1 的二進制數(shù)……………………………………………………… 28 2.4.2 結(jié)合位取反獲取特定位為0 的二進制數(shù)…………………………………………………… 29 2.4.3 總結(jié)…………………………………………………………………………………………… 29 2.5 位運算實戰(zhàn)演練1… ……………………………………………………………………………… 30 2.5.1 給定整型數(shù)a,設(shè)置a 的bit3,保證其他位不變………………………………………… 30 2.5.2 給定整型數(shù)a,設(shè)置a 的bit3~bit7,保持其他位不變… ……………………………… 30 2.5.3 給定整型數(shù)a,清除a 的bit15,保證其他位不變… …………………………………… 302 5.4 給定整型數(shù)a,清除a 的bit15~bit23,保持其他位不變… …………………………… 31 2.5.5 給定整型數(shù)a,取出a 的bit3~bit8… …………………………………………………… 31 2.5.6 用C 語言給寄存器a 的bit7~bit17 賦值937(其余位不受影響)……………………… 31 2.6 位運算實戰(zhàn)演練2… ……………………………………………………………………………… 32 2.6.1 用C 語言將寄存器a 的bit7~bit17 中的值加17(其余位不受影響)…………………… 32 2.6.2 用C 語言給寄存器a 的bit7~bit17 賦值937,同時給bit21~bit25 賦值17… ……… 32 2.7 技術(shù)升級:用宏定義來完成位運算……………………………………………………………… 33 2.7.1 直接用宏來置位……………………………………………………………………………… 33 2.7.2 直接用宏來復(fù)位……………………………………………………………………………… 33 2.7.3 截取變量的部分連續(xù)位……………………………………………………………………… 33 課后題… ………………………………………………………………………………………………… 34 第3 章 指針才是C 語言的精髓… ………………………………………………………… 36 3.1 引言………………………………………………………………………………………………… 36 3.2 指針到底是什么…………………………………………………………………………………… 37 3.2.1 普通變量……………………………………………………………………………………… 37 3.2.2 指針變量……………………………………………………………………………………… 37 3.2.3 變量空間的首字節(jié)地址,作為整個空間的地址…………………………………………… 38 3.2.4 指針變量的類型作用………………………………………………………………………… 38 3.2.5 為什么需要指針……………………………………………………………………………… 39 3.2.6 高級語言如Java、C# 的指針到哪里去了… …………………………………………… 39 3.2.7 指針使用之三部曲…………………………………………………………………………… 40 3.3 理解指針符號……………………………………………………………………………………… 40 3.3.1 星號* 的理解………………………………………………………………………………… 40 3.3.2 取地址符& 的理解… ……………………………………………………………………… 41 3.3.3 指針變量的初始化和指針變量賦值之間的區(qū)別…………………………………………… 41 3.3.4 左值與右值…………………………………………………………………………………… 41 3.3.5 定義指針后,需要關(guān)心的一些內(nèi)容………………………………………………………… 42 3.4 野指針與段錯誤問題……………………………………………………………………………… 43 3.4.1 什么是野指針………………………………………………………………………………… 43 3.4.2 野指針可能引發(fā)的危害……………………………………………………………………… 44 3.4.3 野指針產(chǎn)生的原因…………………………………………………………………………… 44 3.4.4 如何避免野指針……………………………………………………………………………… 45 3.4.5 NULL 到底是什么…………………………………………………………………………… 45 3.4.6 段錯誤產(chǎn)生的原因匯總……………………………………………………………………… 46 3.5 const關(guān)鍵字與指針… …………………………………………………………………………… 46 3.5.1 什么是const… ……………………………………………………………………………… 46 3.5.2 const 對于普通變量的修飾………………………………………………………………… 463 5.3 const 修飾指針的三種形式………………………………………………………………… 46 3.5.4 const 的變量真的不能改嗎………………………………………………………………… 47 3.5.5 為什么要用const…………………………………………………………………………… 48 3.5.6 有關(guān)變量和常量的探討……………………………………………………………………… 48 3.6 深入學(xué)習數(shù)組……………………………………………………………………………………… 49 3.6.1 為什么需要數(shù)組……………………………………………………………………………… 49 3.6.2 從編譯器角度理解數(shù)組……………………………………………………………………… 49 3.6.3 從內(nèi)存角度理解數(shù)組………………………………………………………………………… 49 3.6.4 一位數(shù)組中幾個關(guān)鍵符號的理解…………………………………………………………… 50 3.7 指針與數(shù)組的天生“姻緣”……………………………………………………………………… 50 3.7.1 如何使用指針訪問數(shù)組……………………………………………………………………… 50 3.7.2 從內(nèi)存角度理解指針訪問數(shù)組的實質(zhì)……………………………………………………… 51 3.7.3 指針與數(shù)組類型的匹配問題………………………………………………………………… 51 3.7.4 總結(jié):指針類型決定了指針如何參與運算………………………………………………… 51 3.8 指針類型與強制類型轉(zhuǎn)換………………………………………………………………………… 52 3.8.1 變量數(shù)據(jù)類型的作用………………………………………………………………………… 52 3.8.2 數(shù)據(jù)的存入和讀取…………………………………………………………………………… 53 3.8.3 普通變量的強制轉(zhuǎn)換………………………………………………………………………… 53 3.8.4 指針變量數(shù)據(jù)類型的含義…………………………………………………………………… 56 3.8.5 指針變量數(shù)據(jù)類型的強制轉(zhuǎn)換……………………………………………………………… 56 3.9 指針、數(shù)組與sizeof運算符… …………………………………………………………………… 57 3.9.1 char str[]="hello"; sizeof(str) ,sizeof(str[0]) ,strlen(str)………………………… 58 3.9.2 char str[]="hello"; char *p=str; sizeof(*p) …………………………………………… 58 3.9.3 int b[100]; sizeof(b)… …………………………………………………………………… 58 3.9.4 數(shù)組的傳參…………………………………………………………………………………… 58 3.9.5 #define 和typedef 的區(qū)別………………………………………………………………… 59 3.10 指針與函數(shù)傳參… ……………………………………………………………………………… 60 3.10.1 普通傳參… ………………………………………………………………………………… 60 3.10.2 傳遞地址(指針)…………………………………………………………………………… 61 3.10.3 傳遞數(shù)組… ………………………………………………………………………………… 61 3.10.4 傳遞結(jié)構(gòu)體… ……………………………………………………………………………… 61 3.10.5 傳遞普通值和傳遞地址的異同,以及傳遞地址(指針)應(yīng)該遵循的原則… ………… 62 3.11 輸入型參數(shù)與輸出型參數(shù)… …………………………………………………………………… 62 3.11.1 函數(shù)為什么需要傳參和返回值… ………………………………………………………… 62 3.11.2 函數(shù)傳參中為什么使用const 指針… …………………………………………………… 64 3.11.3 總結(jié)… ……………………………………………………………………………………… 65 課后題… ………………………………………………………………………………………………… 65 第4 章 C 語言復(fù)雜表達式與指針高級應(yīng)用……………………………………………… 67 4.1 引言………………………………………………………………………………………………… 67 4.2 指針數(shù)組與數(shù)組指針……………………………………………………………………………… 67 4.2.1 簡單理解指針數(shù)組與數(shù)組指針……………………………………………………………… 67 4.2.2 分析指針數(shù)組與數(shù)組指針的表達式………………………………………………………… 68 4.3 函數(shù)指針與typedef… …………………………………………………………………………… 69 4.3.1 函數(shù)指針的實質(zhì)(還是指針變量)… ……………………………………………………… 70 4.3.2 函數(shù)指針的書寫和分析方法………………………………………………………………… 70 4.3.3 typedef 關(guān)鍵字的用法……………………………………………………………………… 72 4.4 函數(shù)指針實戰(zhàn)1—用函數(shù)指針調(diào)用執(zhí)行函數(shù)… ……………………………………………… 73 4.5 函數(shù)指針實戰(zhàn)2—結(jié)構(gòu)體內(nèi)嵌函數(shù)指針實現(xiàn)分層… ………………………………………… 75 4.6 再論typedef… …………………………………………………………………………………… 78 4.6.1 輕松理解和應(yīng)用typedef… ………………………………………………………………… 78 4.6.2 typedef 與#define 宏的區(qū)別……………………………………………………………… 80 4.6.3 typedef 與struct… ………………………………………………………………………… 81 4.6.4 typedef 與const… ………………………………………………………………………… 81 4.6.5 使用typedef 的重要意義…………………………………………………………………… 82 4.6.6 二重指針……………………………………………………………………………………… 82 4.7 二維數(shù)組…………………………………………………………………………………………… 83 4.7.1 二維數(shù)組的內(nèi)存映像………………………………………………………………………… 83 4.7.2 識別第一維和第二維………………………………………………………………………… 83 4.7.3 數(shù)組名代表數(shù)組首元素的地址……………………………………………………………… 84 4.7.4 指針訪問二維數(shù)組的兩種方式……………………………………………………………… 84 4.7.5 總結(jié)…………………………………………………………………………………………… 85 課后題… ………………………………………………………………………………………………… 85 第5 章 數(shù)組& 字符串& 結(jié)構(gòu)體& 共用體& 枚舉……………………………………… 88 5.1 引言………………………………………………………………………………………………… 88 5.2 程序中的內(nèi)存從哪里來…………………………………………………………………………… 88 5.2.1 三種內(nèi)存來源:棧(stack)、堆(heap)、數(shù)據(jù)區(qū)(.data)…………………………… 89 5.2.2 棧內(nèi)存特點詳解……………………………………………………………………………… 89 5.3 堆…………………………………………………………………………………………………… 90 5.3.1 堆內(nèi)存特點詳解……………………………………………………………………………… 90 5.3.2 使用堆內(nèi)存注意事項………………………………………………………………………… 91 5.3.3 malloc 的一些細節(jié)表現(xiàn)… ………………………………………………………………… 92 5.4 內(nèi)存中的各個段…………………………………………………………………………………… 92 5.4.1 代碼段、數(shù)據(jù)段、bss 段…………………………………………………………………… 92 5.4.2 特殊數(shù)據(jù)會被放到代碼段…………………………………………………………………… 925 4.3 未初始化或顯式初始化為0 的全局變量放在bss 段… ………………………………… 93 5.4.4 內(nèi)存管理方式的總結(jié)………………………………………………………………………… 93 5.5 C語言的字符串類型… …………………………………………………………………………… 93 5.5.1 C 語言使用指針來管理字符串……………………………………………………………… 93 5.5.2 C 語言中字符串的本質(zhì):指向字符串的存放空間的指針………………………………… 94 5.5.3 指向字符串的指針變量空間和字符串存放的空間是分開的……………………………… 94 5.5.4 存儲多個字符的兩種方式—字符串和字符數(shù)組………………………………………… 94 5.6 字符串和字符數(shù)組的細節(jié)………………………………………………………………………… 95 5.6.1 字符數(shù)組的初始化、sizeof 以及strlen…………………………………………………… 95 5.6.2 字符串的初始化與sizeof、strlen… ……………………………………………………… 96 5.6.3 字符數(shù)組與字符串的本質(zhì)差異……………………………………………………………… 96 5.7 結(jié)構(gòu)體概述………………………………………………………………………………………… 96 5.7.1 結(jié)構(gòu)體使用時先定義結(jié)構(gòu)體類型,再用類型定義變量…………………………………… 96 5.7.2 從數(shù)組到結(jié)構(gòu)體的進步之處………………………………………………………………… 97 5.7.3 結(jié)構(gòu)體變量中的元素如何訪問……………………………………………………………… 97 5.8 結(jié)構(gòu)體的對齊訪問………………………………………………………………………………… 98 5.8.1 結(jié)構(gòu)體對齊訪問實例………………………………………………………………………… 98 5.8.2 結(jié)構(gòu)體為何要對齊訪問……………………………………………………………………… 99 5.8.3 結(jié)構(gòu)體對齊的規(guī)則和運算…………………………………………………………………… 99 5.8.4 手動對齊 … ……………………………………………………………………………… 100 5.8.5 GCC 推薦的對齊指令:_attribute_((packed)) 和_attribute_((aligned(n)))… … 102 5.9 offsetof宏與container_of宏… ……………………………………………………………… 103 5.9.1 由結(jié)構(gòu)體指針進而訪問各元素的原理…………………………………………………… 103 5.9.2 offsetof 宏………………………………………………………………………………… 104 5.9.3 container_of 宏… ……………………………………………………………………… 104 5.9.4 學(xué)習指南和要求…………………………………………………………………………… 105 5.10 共用體(union)… ………………………………………………………………………… 105 5.10.1 共用體的類型聲明、變量定義和使用… ……………………………………………… 105 5.10.2 共用體和結(jié)構(gòu)體的區(qū)別… ……………………………………………………………… 106 5.10.3 共用體的主要用途… …………………………………………………………………… 106 5.11 大小端模式… ………………………………………………………………………………… 107 5.11.1 什么是大小端模式… …………………………………………………………………… 107 5.11.2 用union 來測試機器的大小端模式… ………………………………………………… 108 5.11.3 用指針方式來測試機器的大小端… …………………………………………………… 109 5.11.4 通信系統(tǒng)中的大小端(數(shù)組的大小端)………………………………………………… 109 5.12 枚舉enum… ………………………………………………………………………………… 110 5.12.1 枚舉的作用是什么… ………………………………………………………………………110 5.12.2 C 語言為何需要枚舉… …………………………………………………………………… 1115 12.3 宏定義和枚舉的區(qū)別… …………………………………………………………………… 111 5.12.4 枚舉的定義形式… ………………………………………………………………………… 111 課后題… ……………………………………………………………………………………………… 113 第6 章 C 語言的預(yù)處理、函數(shù)和函數(shù)庫… ……………………………………………… 116 6.1 引言……………………………………………………………………………………………… 116 6.2 C語言為什么需要編譯鏈接… ………………………………………………………………… 116 6.2.1 編譯鏈接的流程………………………………………………………………………………116 6.2.2 編譯鏈接中各種文件擴展名的含義…………………………………………………………118 6.3 預(yù)處理詳解……………………………………………………………………………………… 119 6.3.1 C 語言預(yù)處理的意義…………………………………………………………………………119 6.3.2 預(yù)處理涉及的內(nèi)容……………………………………………………………………………119 6.3.3 使用GCC 進行編譯和鏈接的過程…………………………………………………………119 6.4 常見的預(yù)處理詳解……………………………………………………………………………… 120 6.4.1 文件包含…………………………………………………………………………………… 120 6.4.2 注釋………………………………………………………………………………………… 122 6.4.3 宏定義……………………………………………………………………………………… 123 6.4.4 條件編譯…………………………………………………………………………………… 126 6.5 函數(shù)的本質(zhì)……………………………………………………………………………………… 129 6.5.1 C 語言為什么會有函數(shù)…………………………………………………………………… 129 6.5.2 函數(shù)書寫的一般原則……………………………………………………………………… 129 6.5.3 函數(shù)是動詞、變量是名詞(面向?qū)ο笾蟹謩e叫方法和成員變量)… ………………… 129 6.5.4 函數(shù)的實質(zhì)是數(shù)據(jù)處理器………………………………………………………………… 130 6.6 函數(shù)的基本使用………………………………………………………………………………… 130 6.6.1 函數(shù)三要素:定義、聲明、調(diào)用………………………………………………………… 130 6.6.2 函數(shù)原型和作用………………………………………………………………………………131 6.7 遞歸函數(shù)………………………………………………………………………………………… 131 6.7.1 函數(shù)的調(diào)用機制………………………………………………………………………………131 6.7.2 遞歸函數(shù)…………………………………………………………………………………… 132 6.7.3 使用遞歸的原則:收斂性、棧溢出……………………………………………………… 134 6.7.4 遞歸與循環(huán)的區(qū)別………………………………………………………………………… 135 6.8 庫函數(shù)…………………………………………………………………………………………… 135 6.8.1 什么是函數(shù)庫……………………………………………………………………………… 135 6.8.2 函數(shù)庫的由來……………………………………………………………………………… 135 6.8.3 函數(shù)庫的提供形式:靜態(tài)鏈接庫與動態(tài)鏈接庫………………………………………… 135 6.8.4 庫函數(shù)的使用……………………………………………………………………………… 136 6.9 常見的庫函數(shù)之字符串函數(shù)…………………………………………………………………… 138 6.9.1 什么是字符串……………………………………………………………………………… 1386 9.2 字符串處理函數(shù)…………………………………………………………………………… 138 6.9.3 man 手冊的引入… ……………………………………………………………………… 138 6.9.4 man 手冊的使用… ……………………………………………………………………… 138 6.9.5 常用的字符串處理函數(shù)…………………………………………………………………… 139 6.10 常見的庫函數(shù)之數(shù)學(xué)庫函數(shù)… ……………………………………………………………… 140 6.10.1 數(shù)學(xué)庫函數(shù)… …………………………………………………………………………… 140 6.10.2 計算開平方… …………………………………………………………………………… 140 6.10.3 鏈接時加-lm… ……………………………………………………………………………141 6.11 制作靜態(tài)鏈接庫并使用… …………………………………………………………………… 141 6.12 制作動態(tài)鏈接庫并使用… …………………………………………………………………… 143 課后題… ……………………………………………………………………………………………… 144 第7 章 存儲類& 作用域& 生命周期& 鏈接屬性………………………………………… 147 7.1 引言……………………………………………………………………………………………… 147 7.2 概念解析………………………………………………………………………………………… 147 7.2.1 存儲類……………………………………………………………………………………… 147 7.2.2 作用域……………………………………………………………………………………… 148 7.2.3 生命周期…………………………………………………………………………………… 148 7.2.4 鏈接屬性…………………………………………………………………………………… 148 7.3 Linux下C程序的內(nèi)存映像… ………………………………………………………………… 149 7.3.1 代碼段、rodata 段(只讀數(shù)據(jù)段)… …………………………………………………… 149 7.3.2 數(shù)據(jù)段、bss 段…………………………………………………………………………… 149 7.3.3 堆…………………………………………………………………………………………… 149 7.3.4 文件映射區(qū)………………………………………………………………………………… 149 7.3.5 !150 7.3.6 內(nèi)核映射區(qū)………………………………………………………………………………… 150 7.3.7 操作系統(tǒng)下和裸機下C 程序加載執(zhí)行的差異… ……………………………………… 150 7.4 存儲類相關(guān)的關(guān)鍵字1… ……………………………………………………………………… 150 7.4.1 auto………………………………………………………………………………………… 150 7.4.2 static… ………………………………………………………………………………………151 7.4.3 register… ……………………………………………………………………………………151 7.5 存儲類相關(guān)的關(guān)鍵字2… ……………………………………………………………………… 152 7.5.1 extern……………………………………………………………………………………… 152 7.5.2 volatile… ………………………………………………………………………………… 153 7.5.3 restrict… ………………………………………………………………………………… 154 7.5.4 typedef… ………………………………………………………………………………… 154 7.6 作用域詳解……………………………………………………………………………………… 154 7.6.1 局部變量的代碼塊作用域………………………………………………………………… 1547 6.2 函數(shù)名和全局變量的文件作用域………………………………………………………… 155 7.7 變量的生命周期………………………………………………………………………………… 155 7.7.1 研究變量生命周期的意義………………………………………………………………… 155 7.7.2 棧變量的生命周期………………………………………………………………………… 156 7.7.3 堆變量的生命周期………………………………………………………………………… 156 7.7.4 數(shù)據(jù)段、bss 段變量的生命周期………………………………………………………… 156 7.7.5 代碼段、只讀段的生命周期……………………………………………………………… 156 7.8 鏈接屬性………………………………………………………………………………………… 156 7.8.1 C 語言程序的組織架構(gòu):多個C 文件+ 多個h 文件… ……………………………… 156 7.8.2 編譯以文件為單位、鏈接以工程為單位………………………………………………… 157 7.8.3 三種鏈接屬性:外連接、內(nèi)鏈接、無鏈接……………………………………………… 157 7.8.4 函數(shù)和全局變量的命名沖突問題………………………………………………………… 157 7.8.5 static 的第二種用法:修飾全局變量和函數(shù)…………………………………………… 158 課后題… ……………………………………………………………………………………………… 158 第8 章 C 語言關(guān)鍵細節(jié)討論… …………………………………………………………… 159 8.1 引言……………………………………………………………………………………………… 159 8.2 操作系統(tǒng)概述…………………………………………………………………………………… 159 8.2.1 什么是操作系統(tǒng)…………………………………………………………………………… 159 8.2.2 C 庫函數(shù)…………………………………………………………………………………… 160 8.2.3 操作系統(tǒng)的重大意義…………………………………………………………………………161 8.3 main函數(shù)返回值… …………………………………………………………………………… 162 8.3.1 普通函數(shù)的返回值………………………………………………………………………… 162 8.3.2 main 函數(shù)的返回值… …………………………………………………………………… 163 8.3.3 誰調(diào)用了main 函數(shù)……………………………………………………………………… 164 8.4 argc、argv與main函數(shù)的傳參… …………………………………………………………… 164 8.5 void類型的本質(zhì)………………………………………………………………………………… 165 8.6 C語言中的NULL… …………………………………………………………………………… 166 8.6.1 NULL 的定義……………………………………………………………………………… 166 8.6.2 '\0' 、 '0' 、0 和NULL 的區(qū)別… ……………………………………………………… 167 8.7 運算中的臨時匿名變量………………………………………………………………………… 168 8.7.1 C 語言和匯編語言的區(qū)別………………………………………………………………… 168 8.7.2 強制類型轉(zhuǎn)換……………………………………………………………………………… 168 8.7.3 使用臨時變量來理解不同數(shù)據(jù)類型之間的運算………………………………………… 169 8.8 順序結(jié)構(gòu)………………………………………………………………………………………… 169 8.8.1 C 語言中的結(jié)構(gòu)…………………………………………………………………………… 169 8.8.2 編譯過程中的順序結(jié)構(gòu)…………………………………………………………………… 169 8.8.3 思考:為什么本質(zhì)都是順序結(jié)構(gòu)………………………………………………………… 170 8.9 程序調(diào)試………………………………………………………………………………………… 170 8.9.1 程序調(diào)試手段……………………………………………………………………………… 170 8.9.2 調(diào)試(DEBUG) 版本和發(fā)行(RELEASE) 版本的區(qū)別… ………………………………171 8.9.3 debug 宏的使用方法… ……………………………………………………………………171 課后題… ……………………………………………………………………………………………… 172 第9 章 鏈表& 狀態(tài)機& 多線程…………………………………………………………… 173 9.1 引言……………………………………………………………………………………………… 173 9.2 鏈表的引入……………………………………………………………………………………… 173 9.2.1 數(shù)組的缺陷………………………………………………………………………………… 173 9.2.2 鏈表是什么樣子的………………………………………………………………………… 174 9.2.3 鏈表的作用是什么………………………………………………………………………… 174 9.3 單鏈表的實現(xiàn)之構(gòu)建第一個節(jié)點……………………………………………………………… 175 9.3.1 不實用卻意義重大的簡單鏈表…………………………………………………………… 175 9.3.2 從簡單的鏈表開始………………………………………………………………………… 175 9.3.3 單鏈表的節(jié)點構(gòu)成………………………………………………………………………… 175 9.3.4 使用堆內(nèi)存創(chuàng)建一個節(jié)點………………………………………………………………… 176 9.3.5 鏈表的頭指針……………………………………………………………………………… 177 9.3.6 構(gòu)建第一個簡單的鏈表…………………………………………………………………… 177 9.4 單鏈表的實現(xiàn)之從尾部插入節(jié)點……………………………………………………………… 177 9.4.1 從尾部插入節(jié)點…………………………………………………………………………… 177 9.4.2 構(gòu)建第一個簡單的鏈表…………………………………………………………………… 178 9.4.3 什么是頭節(jié)點……………………………………………………………………………… 179 9.5 單鏈表的算法之從頭部插入節(jié)點……………………………………………………………… 180 9.5.1 鏈表頭部插入思路解析…………………………………………………………………… 180 9.5.2 箭頭非指向……………………………………………………………………………………181 9.6 單鏈表的算法之遍歷節(jié)點……………………………………………………………………… 181 9.6.1 什么是遍歷……………………………………………………………………………………181 9.6.2 如何遍歷單鏈表………………………………………………………………………………181 9.6.3 代碼分析…………………………………………………………………………………… 182 9.7 單鏈表的算法之刪除節(jié)點……………………………………………………………………… 182 9.7.1 為什么要刪除節(jié)點………………………………………………………………………… 182 9.7.2 注意堆內(nèi)存的釋放………………………………………………………………………… 183 9.7.3 設(shè)計一個刪除節(jié)點算法…………………………………………………………………… 184 9.8 單鏈表的算法之逆序…………………………………………………………………………… 184 9.8.1 什么是鏈表的逆序………………………………………………………………………… 184 9.8.2 單鏈表的逆序算法分析…………………………………………………………………… 185 9.8.3 編程實現(xiàn)逆序算法………………………………………………………………………… 185 雙鏈表的引入和基本實現(xiàn)……………………………………………………………………… 187 9.9.1 單鏈表的優(yōu)缺點…………………………………………………………………………… 187 9.9.2 雙鏈表的結(jié)構(gòu)……………………………………………………………………………… 187 9.10 雙鏈表的算法之插入節(jié)點… ………………………………………………………………… 188 9.10.1 尾部插入… ……………………………………………………………………………… 188 9.10.2 頭部插入… ……………………………………………………………………………… 189 9.11 雙鏈表的算法之遍歷… ……………………………………………………………………… 190 9.11.1 正向遍歷… ……………………………………………………………………………… 190 9.11.2 逆向遍歷… ……………………………………………………………………………… 190 9.12 雙鏈表的算法之刪除節(jié)點… ………………………………………………………………… 191 9.13 Linux內(nèi)核鏈表………………………………………………………………………………… 192 9.13.1 前述鏈表數(shù)據(jù)區(qū)域的局限性… ………………………………………………………… 193 9.13.2 解決思路:數(shù)據(jù)區(qū)的結(jié)構(gòu)體的封裝由用戶實現(xiàn),通用部分通過調(diào)用函數(shù)實現(xiàn)… … 193 9.13.3 內(nèi)核鏈表的設(shè)計思路… ………………………………………………………………… 193 9.13.4 list.h 文件簡介…………………………………………………………………………… 194 9.14 內(nèi)核鏈表的基本算法和使用簡介… ………………………………………………………… 196 9.14.1 內(nèi)核鏈表的常用操作… ………………………………………………………………… 196 9.14.2 內(nèi)核鏈表的使用實踐… ………………………………………………………………… 197 9.15 什么是狀態(tài)機… ……………………………………………………………………………… 198 9.15.1 有限狀態(tài)機… …………………………………………………………………………… 199 9.15.2 兩種狀態(tài)機:Moore 型和Mealy 型…………………………………………………… 199 9.15.3 狀態(tài)機的主要用途… …………………………………………………………………… 200 9.15.4 狀態(tài)機解決了什么問題… ……………………………………………………………… 200 9.16 用C語言實現(xiàn)簡單的狀態(tài)機… ……………………………………………………………… 201 9.16.1 題目:開鎖狀態(tài)機… …………………………………………………………………… 201 9.16.2 題目分析… ……………………………………………………………………………… 201 9.17 多線程簡介… ………………………………………………………………………………… 203 9.17.1 操作系統(tǒng)下的并行執(zhí)行機制… ………………………………………………………… 203 9.17.2 進程和線程的區(qū)別和聯(lián)系… …………………………………………………………… 204 9.17.3 多線程的優(yōu)勢… ………………………………………………………………………… 204 課后題… ……………………………………………………………………………………………… 204 第10 章 程序員和編譯器的曖昧…………………………………………………………… 206 10.1 引言… ………………………………………………………………………………………… 206 10.2 編程工作的演進史… ………………………………………………………………………… 206 10.2.1 CPU 與二進制…………………………………………………………………………… 206 10.2.2 編程語言的革命… ……………………………………………………………………… 207 10.3 程序員、編譯器和CPU之間的三角戀……………………………………………………… 207 10.3.1 程序員與CPU 的之間的“翻譯”—編譯器………………………………………… 207 10.3.2 高級語言與低級語言的差別… ………………………………………………………… 208 10.4 像編譯器一樣思考吧—理論篇… ………………………………………………………… 208 10.4.1 編譯器的結(jié)構(gòu)… ………………………………………………………………………… 208 10.4.2 語法是什么?語法就是編譯器的習性… ……………………………………………… 208 10.5 像編譯器一樣思考吧—實戰(zhàn)篇… ………………………………………………………… 209 10.5.1 充分地利用語法規(guī)則,寫出簡潔、高效的代碼… …………………………………… 209 10.5.2 復(fù)雜表達式理解… ……………………………………………………………………… 209 課后題… ……………………………………………………………………………………………… 214 附錄 答案…………………………………………………………………………………… 215 第1章 課后題答案…………………………………………………………………………………… 215 第2章 課后題答案…………………………………………………………………………………… 217 第3章 課后題答案…………………………………………………………………………………… 218 第4章 課后題答案…………………………………………………………………………………… 220 第5章 課后題答案…………………………………………………………………………………… 222 第6章 課后題答案…………………………………………………………………………………… 226 第7章 課后題答案…………………………………………………………………………………… 228 第8章 課后題答案…………………………………………………………………………………… 230 第9章 課后題答案…………………………………………………………………………………… 231 第10章 課后題答案… ……………………………………………………………………………… 236
你還可能感興趣
我要評論
|