C語言最佳實踐
魏永明
買這商品的人也買了...
-
$2,210$2,100 -
$960$864 -
$550$550 -
$700$665 -
$301並行演算法設計與性能優化
-
$948$901 -
$454深入淺出 HTTPS : 從原理到實戰
-
$880$748 -
$774$735 -
$602用“芯”探核基於龍芯的 Linux 內核探索解析
-
$1,680$1,596 -
$594$564 -
$708$673 -
$594$564 -
$1,870$1,777 -
$505極限黑客攻防:CTF 賽題揭秘
-
$419$398 -
$662$623 -
$774$735 -
$400C++ 新經典:模板與泛型編程
-
$378程序員的制勝技
-
$948$901 -
$534$507 -
$458C++ 項目開發全程實錄, 3/e
-
$458C語言項目開發全程實錄, 3/e
相關主題
商品描述
本書是魏永明近30年來開發和維護MiniGUI、HVML等開源項目的經驗總結,旨在幫助有一定C程序編寫經驗的軟件工程師在短時間內有效提高設計能力和編碼水平。全書分為?3?篇。基礎篇從可讀性和可維護性出發,闡述瞭如何提高代碼的可讀性、用好寫好頭文件、正確理解編譯警告並消除潛在問題、定義和使用常量等,介紹瞭如何有效利用構建系統生成器(CMake)來維護項目;模式篇闡述了常見的C程序接口設計模式,說明瞭如何在C程序中解耦代碼和數據、利用子驅動程序實現模型、設計可加載模塊等,介紹了狀態機的概念以及在C程序中如何利用狀態機實現分詞器、解析器等;質量篇從性能和單元測試出發,闡述瞭如何在C程序中避免編寫低效代碼、進行單元測試、使用常見的單元測試框架等,介紹了高效調試C程序的若乾技巧和工具。
本書適合從事系統軟件、嵌入式或物聯網開發的C程序員、電腦相關專業高年級本科生和研究生閱讀。
作者簡介
魏永明,获清华大学工学学士、硕士学位,飞漫软件创始人,2013年度“开源软件杰出贡献人物”,2023年世界开源软件Top100贡献榜人物。1999年发布了开源软件MiniGUI并持续研发至今。编(译)著有《MiniGUI剖析》、《Linux 实用教程》、《Linux 设备驱动程序》(二、三版)等技术著作。2018年11月,发起合璧操作系统开源协作项目;2020年8月,提出首款描述式编程语言HVML;2022年7月,开源发布 HVML 解释器及渲染器。
目錄大綱
第 一篇 基礎篇
第 1章 提高代碼可讀性 3
1.1 代碼可讀性的級別 3
1.2 壞代碼的特點 4
1.2.1 壞代碼實例 5
1.2.2 妙手理碼 7
1.3 編碼風格的內容 9
1.3.1 Linux內核編碼風格的一些規定 10
1.3.2 其他常見的編碼風格 11
1.4 提高代碼可讀性的最佳實踐 14
1.4.1 守好“80列”這條紅線 14
1.4.2 空格、大括號位置及縮進 15
1.4.3 指針聲明和定義中的星號位置 16
1.4.4 善用類型定義 16
1.4.5 命名規則保持一致 19
1.4.6 正確書寫註釋 20
1.4.7 優雅編寫條件編譯代碼 21
1.5 其他有關編碼風格的最佳實踐 23
1.5.1 下畫線前綴的使用 24
1.5.2 錯誤處理及集中返回 24
1.5.3 參數的合法性檢查 28
1.6 命名的藝術 32
1.7 實例分析 34
1.7.1 PurC函數庫頭文件 34
1.7.2 經典的list_head結構體及其接口 37
第 2章 用好寫好頭文件 40
2.1 重新認識頭文件 40
2.1.1 頭文件的作用 40
2.1.2 頭文件的分類 42
2.1.3 頭文件機制的復雜性 47
2.2 濫用系統頭文件的負面影響 61
2.3 自定義頭文件中的常見問題 62
2.3.1 不使用或不當定義頭文件保衛宏 62
2.3.2 未正確處理和C++程序混用的情形 63
2.3.3 未處理可能的重復定義 65
2.3.4 包含不該出現在頭文件中的內容 66
2.3.5 未妥善處理可能的可移植性問題 68
2.4 頭文件相關的最佳實踐 70
2.4.1 兩大原則 70
2.4.2 頭文件的劃分及典型內容 71
2.4.3 頭文件的組織 77
第3章 消除編譯警告 83
3.1 為什麽不能忽視編譯警告 83
3.1.1 潛在問題恐釀成大禍 83
3.1.2 解讀編譯警告 84
3.2 常見的編譯警告及其分類 88
3.2.1 預處理警告 88
3.2.2 未使用警告 90
3.2.3 未初始化警告 93
3.2.4 類型安全警告 95
3.2.5 邏輯運算相關的警告 99
3.2.6 格式化相關警告 102
3.2.7 詞法警告 105
3.2.8 其他警告 109
3.3 編譯警告和函數屬性 110
3.3.1 malloc屬性 111
3.3.2 nonnull屬性 111
3.3.3 warn_unused_result屬性 112
3.3.4 format屬性 112
3.3.5 其他函數屬性 113
3.4 消除編譯警告只是開始 114
第4章 常量的定義和使用 116
4.1 常見的常量使用問題 116
4.1.1 立即數常量 116
4.1.2 字符串常量 119
4.2 正確定義和使用常量 121
4.2.1 立即數常量 121
4.2.2 字符串常量 127
4.3 優雅定義和使用常量 127
4.3.1 借助編譯器 127
4.3.2 使用宏生成常量和代碼 130
4.3.3 巧用編譯時斷言 131
4.4 字符串的原子化 133
第5章 充分利用構建系統生成器 136
5.1 常用構建系統和構建系統生成器 136
5.2 CMake影響編碼的選項或功能 138
5.2.1 構建類型 138
5.2.2 處理平臺差異 139
5.2.3 自動生成代碼 142
5.3 CMake構建體系模板 143
5.3.1 整體結構和復制步驟 143
5.3.2 多平臺支持 149
5.3.3 檢測系統頭文件、函數或結構體成員 150
5.3.4 查找第三方軟件包 151
5.3.5 自定義功能測試 152
第二篇 模式篇
第6章 接口設計模式 155
6.1 何謂好接口 155
6.2 兩個接口設計原則 157
6.3 一般性方法和技巧 161
6.3.1 完備性的保證 161
6.3.2 參數及返回值 162
6.4 模式1:抽象數據類型 164
6.4.1 範例1:變體 166
6.4.2 範例2:讀寫流 169
6.4.3 範例3:描述符或句柄 173
6.5 模式2:抽象算法 174
6.5.1 範例1:標準C庫的
qsort()函數及其擴展 177
6.5.2 範例2:MiniGUI的曲線生成器函數 179
6.6 模式3:上下文 181
6.6.1 顯式上下文 181
6.6.2 隱式上下文 183
6.6.3 範例1:標準C庫的錯誤碼 184
6.6.4 範例2:PurC實例 185
6.7 模式4:事件驅動 186
6.7.1 範例1:MiniGUI消息驅動接口 187
6.7.2 範例2:glib的事件驅動接口 196
6.7.3 事件處理器的粒度 199
6.8 模式5:通用數據結構 202
6.8.1 範例1:在節點結構體中保留用戶數據成員 202
6.8.2 範例2:在用戶結構體中包含通用節點結構體 204
6.9 模式6:同類聚合 209
6.9.1 範例1:STDIO接口中的同類聚合 210
6.9.2 範例2:MiniGUI中圖片裝載接口的同類聚合 212
6.9.3 範例3:PurC變體接口中的同類聚合 212
6.9.4 避免過度設計 214
6.10 模式7:遍歷和迭代 215
6.10.1 方法1:遍歷宏 215
6.10.2 方法2:遍歷回調 218
6.10.3 方法3:迭代器 220
6.11 模式8:接口的擴展和兼容性 222
6.11.1 方法1:新舊接口共存 222
6.11.2 方法2:舊接口只是新接口的繞轉接口 224
6.11.3 方法3:強制使用新接口,將舊接口標記為廢棄或移除 225
6.11.4 方法4:預留擴展能力 225
6.11.5 擴展接口需要考慮的因素 229
6.12 綜合範例:PurC中的有序數組 229
第7章 解耦代碼和數據 233
7.1 解耦代碼和數據的重要性 233
7.2 一個簡單的例子 235
7.2.1 數據和代碼耦合的版本 235
7.2.2 數據和代碼解耦的版本 236
7.3 再來一個例子 238
7.4 更復雜的例子 241
7.4.1 最初的實現 243
7.4.2 改進的版本 245
7.4.3 進一步優化 247
7.5 自動生成代碼 249
7.5.1 使用宏生成代碼 249
7.5.2 使用程序生成代碼 251
第8章 子驅動程序實現模型 256
8.1 抽象的重要性 256
8.2 隨處可見的子驅動程序實現模型 257
8.3 子驅動程序實現模型的構成 258
8.3.1 子驅動程序上下文結構體指針 259
8.3.2 子驅動程序操作集 260
8.3.3 普通文件流對象的子驅動程序實現 261
8.3.4 內存緩沖區流對象的子驅動程序實現 262
8.3.5 進一步思考 264
8.4 正確區分機制和策略 265
8.5 子驅動程序實現模型的演進 266
8.5.1 最初的設計和實現 266
8.5.2 反思一:子驅動程序操作集的定義是否足夠完備和靈活 269
8.5.3 反思二:子驅動程序的實現中是否含有不該有的策略 271
8.5.4 反思三:還有哪些可以改進的地方 273
第9章 動態加載模塊 275
9.1 可加載模塊的好處 275
9.2 軟件棧和可加載模塊的設計原則 275
9.3 可加載模塊的實現原理和要點 278
9.3.1 可加載模塊的底層機制 278
9.3.2 可加載模塊新舊版本的兼容性 278
9.3.3 可加載模塊的實現要點 280
9.4 使用可加載模塊支持新的圖片格式 281
9.5 重用已有子驅動程序的實現 285
9.5.1 合成器操作集 286
9.5.2 合成器相關的應用程序接口 287
9.5.3 派生一個自己的合成器 288
9.5.4 裝載模塊定義的默認合成器 289
第 10章 狀態機 292
10.1 狀態機的概念 292
10.2 定義一個狀態機 293
10.3 正確理解狀態機 295
10.4 狀態機在各類解析器中的應用 297
10.4.1 簡單示例:判斷C語言立即數的進制 297
10.4.2 復雜示例:HTML解析器中的分詞器 299
第三篇 質量篇
第 11章 為性能編碼 309
11.1 何謂“性能” 309
11.2 提高性能的3個基本原則 312
11.2.1 不要做無用功 312
11.2.2 殺雞莫用牛刀 314
11.2.3 避免濫用內存分配 315
11.3 實例研究:字符串匹配 318
11.3.1 最直接的實現 319
11.3.2 利用哈希算法進行優化 320
11.3.3 字符串的原子化 326
11.4 實例研究:如何判斷一個自然數是不是素數 331
11.4.1 小於16的自然數 331
11.4.2 可表示為無符號短整型的自然數 332
11.4.3 可表示為64位無符號長整型的自然數 334
11.5 實例研究:像素混合的並行計算 335
11.6 實例研究:達夫設備 338
第 12章 單元測試 340
12.1 單元測試的基本概念和重要性 340
12.2 單元測試的基本方法 341
12.2.1 單元測試可以無處不在 341
12.2.2 單元測試方法和測試用例的選擇 342
12.2.3 單元測試的自動化 348
12.3 單元測試框架 354
12.3.1 GLib Testing 354
12.3.2 GoogleTest 357
12.3.3 CTest 358
12.4 實例研究:HVML MATH對象的eval方法 359
12.4.1 測試目標 359
12.4.2 測試方法 360
12.4.3 使用現有可信賴的工具生成預期結果 362
第 13章 高效調試 364
13.1 高效調試的基本原則 364
13.2 C程序常見錯誤分類 365
13.2.1 編譯、鏈接錯誤 365
13.2.2 疑難雜症 366
13.3 內存使用錯誤 367
13.3.1 靜態數據使用錯誤 367
13.3.2 堆使用錯誤 372
13.3.3 棧使用錯誤 379
13.4 內存診斷工具 381
13.4.1 Efence 381
13.4.2 ASAN 384
13.4.3 Valgrind 386
13.5 日誌 391
後記 396