更多课程 选择中心

C/C++培训
达内IT学院

400-111-8989

电子书推荐:编写高质量代码:改善C程序代码的125个建议

  • 发布:马伟 著
  • 来源:机械工业出版社出版
  • 时间:2017-09-07 15:30

编写高质量代码:改善C程序代码的125个建议, 机械工业出版社出版,作者:马伟 著。本书是一本关于C语言最佳实践的集大成之作,它从C语言本身、C程序的架构设计和思想、C程序的编码规范和习惯等三大方面对125个经典的问题给出了解决方案,为C开发者提高开发效率和编写高质量的C代码提供了宝贵的建议。对于每一个建议,作者不仅给出了被实践证明为比较优秀的解决方案,而且还给出了被误用或被错误理解的不好的解决方案,形成了鲜明对比。


这本书是把《C Programing Language》,《C和指针》,《C专家编程》,《C陷阱与缺陷》里大部分干货以最简明最逻辑性,毫无废话的全串了一遍。甚为难得!常翻常新的一套书。

这本书讲的不是语言,而是计算机程序设计。如果一门语言在你脑海里只是一堆零散的语法知识点,这本书能让语言成为生长在你脑子里的技能。

《编写高质量代码:改善C程序代码的125个建议》图书目录

第1章数据,程序设计之根本1

建议1:认识ANSIC1

建议2:防止整数类型产生回绕与溢出6

建议2—1:char类型变量的值应该限制在signedchar与unsignedchar的交集范围内11

建议2—2:使用显式声明为signedchar或unsignedchar的类型来执行算术运算11

建议2—3:使用rsize_t或size_t类型来表示一个对象所占用空间的整数值单位13

建议2—4:禁止把size_t类型和它所代表的真实类型混用16

建议2—5:小心使用无符号类型带来的陷阱16

建议2—6:防止无符号整数回绕19

建议2—7:防止有符号整数溢出24

建议3:尽量少使用浮点类型28

建议3—1:了解IEEE754浮点数29

建议3—2:避免使用浮点数进行精确计算39

建议3—3:使用分数来精确表达浮点数43

建议3—4:避免直接在浮点数中使用“==”操作符做相等判断47

建议3—5:避免使用浮点数作为循环计数器50

建议3—6:尽量将浮点运算中的整数转换为浮点数51

建议4:数据类型转换必须做范围检查52

建议4—1:整数转换为新类型时必须做范围检查53

建议4—2:浮点数转换为新类型时必须做范围检查56

建议5:使用有严格定义的数据类型57

建议6:使用typedef来定义类型的新别名61

建议6—1:掌握typedef的4种应用形式61

建议6—2:小心使用typedef带来的陷阱65

建议6—3:typedef不同于#define65

建议7:变量声明应该力求简洁66

建议7—1:尽量不要在一个声明中声明超过一个的变量67

建议7—2:避免在嵌套的代码块之间使用相同的变量名68

建议8:正确地选择变量的存储类型68

建议8—1:定义局部变量时应该省略auto关键字69

建议8—2:慎用extern声明外部变量70

建议8—3:不要混淆static变量的作用72

建议8—4:尽量少使用register变量75

建议9:尽量不要在可重入函数中使用静态(或全局)变量76

建议10:尽量少使用全局变量78

建议11:尽量使用const声明值不会改变的变量78

第2章保持严谨的程序设计,一切从表达式开始做起81

建议12:尽量减少使用除法运算与求模运算81

建议12—1:用倒数相乘来实现除法运算82

建议12—2:使用牛顿迭代法求除数的倒数84

建议12—3:用减法运算来实现整数除法运算86

建议12—4:用移位运算实现乘除法运算86

建议12—5:尽量将浮点除法转化为相应的整数除法运算87

建议13:保证除法和求模运算不会导致除零错误87

建议14:适当地使用位操作来提高计算效率88

建议14—1:尽量避免对未知的有符号数执行位操作89

建议14—2:在右移中合理地选择0或符号位来填充空出的位90

建议14—3:移位的数量必须大于等于0且小于操作数的位数90

建议14—4:尽量避免在同一个数据上执行位操作与算术运算91

建议15:避免操作符混淆92

建议15—1:避免“=”与“==”混淆92

建议15—2:避免“|”与“||”混淆94

建议15—3:避免“&”与“&&”混淆95

建议16:表达式的设计应该兼顾效率与可读性95

建议16—1:尽量使用复合赋值运算符95

建议16—2:尽量避免编写多用途的、太复杂的复合表达式97

建议16—3:尽量避免在表达式中使用默认的优先级98

第3章程序控制语句应该保持简洁高效101

建议17:if语句应该尽量保持简洁,减少嵌套的层数101

建议17—1:先处理正常情况,再处理异常情况101

建议17—2:避免“悬挂”的else102

建议17—3:避免在if/else语句后面添加分号“;”105

建议17—4:对深层嵌套的if语句进行重构106

建议18:谨慎0值比较108

建议18—1:避免布尔型与0或1进行比较108

建议18—2:整型变量应该直接与0进行比较109

建议18—3:避免浮点变量用“==”或“!=”与0进行比较109

建议18—4:指针变量应该用“==”或“!=”与NULL进行比较111

建议19:避免使用嵌套的“?:”111

建议20:正确使用for循环114

建议20—1:尽量使循环控制变量的取值采用半开半闭区间写法114

建议20—2:尽量使循环体内工作量达到最小化115

建议20—3:避免在循环体内修改循环变量115

建议20—4:尽量使逻辑判断语句置于循环语句外层116

建议20—5:尽量将多重循环中最长的循环放在最内层,最短的循环放在最外层117

建议20—6:尽量将循环嵌套控制在3层以内117

建议21:适当地使用并行代码来优化for循环117

建议22:谨慎使用do/while与while循环118

建议22—1:无限循环优先选用for(;;),而不是while(1)118

建议22—2:优先使用for循环替代do/while与while循环119

建议23:正确地使用switch语句120

建议23—1:不要忘记在case语句的结尾添加break语句120

建议23—2:不要忘记在switch语句的结尾添加default语句122

建议23—3:不要为了使用case语句而刻意构造一个变量122

建议23—4:尽量将长的switch语句转换为嵌套的switch语句123

建议24:选择合理的case语句排序方法124

建议24—1:尽量按照字母或数字顺序来排列各条case语句124

建议24—2:尽量将情况正常的case语句排在最前面125

建议24—3:尽量根据发生频率来排列各条case语句125

建议25:尽量避免使用goto语句125

建议26:区别continue与break语句127

第4章函数同样需要保持简洁高效129

建议27:理解函数声明129

建议28:理解函数原型131

建议29:尽量使函数的功能单一132

建议30:避免把没有关联的语句放在一个函数中135

建议31:函数的抽象级别应该在同一层次136

建议32:尽可能为简单功能编写函数137

建议33:避免多段代码重复做同一件事情138

建议34:尽量避免编写不可重入函数140

建议34—1:避免在函数中使用static局部变量140

建议34—2:避免函数返回指向静态数据的指针140

建议34—3:避免调用任何不可重入函数142

建议34—4:对于全局变量,应通过互斥信号量(即P、V操作)或者中断机制等方法来保证函数的线程安全143

建议34—5:理解可重入函数与线程安全函数之间的关系144

建议35:尽量避免设计多参数函数145

建议35—1:没有参数的函数必须使用void填充145

建议35—2:尽量避免在非调度函数中使用控制参数147

建议35—3:避免将函数的参数作为工作变量148

建议35—4:使用const防止指针类型的输入参数在函数体内被意外修改149

建议36:没有返回值的函数应声明为void类型149

建议37:确保函数体的“入口”与“出口”安全性150

建议37—1:尽量在函数体入口处对参数做有效性检查150

建议37—2:尽量在函数体出口处对return语句做安全性检查151

建议38:在调用函数时,必须对返回值进行判断,同时对错误的返回值还要有相应的错误处理152

建议39:尽量减少函数本身或者函数间的递归调用153

建议40:尽量使用inline内联函数来替代#define宏154

第5章不会使用指针的程序员是不合格的157

建议41:理解指针变量的存储实质157

建议42:指针变量必须初始化162

建议43:区别“int*p=NULL”和“*p=NULL”163

建议44:理解空(null)指针与NULL指针164

建议44—1:区别空(null)指针与NULL指针的概念164

建议44—2:用NULL指针终止对递归数据结构的间接引用166

建议44—3:用NULL指针作函数调用失败时的返回值169

建议44—4:用NULL指针作警戒值170

建议44—5:避免对NULL指针进行解引用170

建议45:谨慎使用void指针171

建议45—1:避免对void指针进行算术操作172

建议45—2:如果函数的参数可以是任意类型指针,应该将其参数声明为void*173

建议46:避免使用指针的长度确定它所指向类型的长度175

建议47:避免把指针转换为对齐要求更严格的指针类型176

建议48:避免将一种类型的操作符应用于另一种不兼容的类型177

建议49:谨慎指针与整数之间的转换180

建议50:区别“constint*p”与“int*constp”180

建议51:深入理解函数参数的传递方式183

建议51—1:理解函数参数的传递过程183

建议51—2:掌握函数的参数传递方式188

建议51—3:如果函数的参数是指针,避免用该指针去申请动态内存191

建议51—4:尽量避免使用可变参数195

第6章数组并非指针199

建议52:理解数组的存储实质199

建议52—1:理解数组的存储布局199

建议52—2:理解&a(0)和&a的区别203

建议52—3:理解数组名a作为右值和左值的区别203

建议53:避免数组越界204

建议53—1:尽量显式地指定数组的边界207

建议53—2:对数组做越界检查,确保索引值位于合法的范围之内209

建议53—3:获取数组的长度时不要对指针应用sizeof操作符210

建议54:数组并非指针213

建议55:理解数组与指针的可交换性217

建议56:禁止将一个指向非数组对象的指针加上或减去一个整数219

建议57:禁止对两个并不指向同一个数组的指针进行相减或比较220

建议58:若结果值并不引用合法的数组元素,不要将指针加上或减去一个整数220

建议59:细说缓冲区溢出220

建议60:区别指针数组和数组指针226

建议61:深入理解数组参数227

第7章结构、位域和枚举231

建议62:结构体的设计要遵循简单、单一原则231

建议62—1:尽量使结构体的功能单一232

建议62—2:尽量减小结构体间关系的复杂度234

建议62—3:尽量使结构体中元素的个数适中235

建议62—4:合理划分与改进结构体以提高空间效率236

建议63:合理利用结构体内存对齐原理来提高程序效率237

建议64:结构体的长度不一定等于各个成员的长度之和249

建议65:避免在结构体之间执行逐字节比较250

建议66:谨慎使用位域251

建议67:谨慎使用枚举252

建议68:禁止在位域成员上调用offsetof宏254

建议69:深入理解结构体数组和结构体指针255

第8章字符与字符串260

建议70:不要忽视字符串的null(’\0’)结尾符260

建议70—1:正确认识字符数组和字符串261

建议70—2:字符数组必须能够同时容纳字符数据和null结尾符262

建议70—3:谨慎字符数组的初始化263

建议71:尽量使用const指针来引用字符串常量264

建议72:区别strlen函数与sizeof运算符264

建议73:在使用不受限制的字符串函数时,必须保证结果字符串不会溢出内存265

建议73—1:避免字符串拷贝发生溢出266

建议73—2:区别串拷贝strcpy与内存拷贝memcpy270

建议73—3:避免strcpy与memcpy函数内存重叠273

建议73—4:区别字符串比较与内存比较278

建议73—5:避免strcat函数发生内存重叠与溢出283

建议74:谨慎strtok函数的不可重入性287

建议75:掌握字符串查找技术292

建议75—1:使用strchr与strrchr函数查找单个字符292

建议75—2:使用strpbrk函数查找多个字符293

建议75—3:使用strstr函数查找一个子串294

建议75—4:区别strspn与strcspn函数295

第9章文件系统298

建议76:谨慎使用printf和scanf函数299

建议77:谨慎文件打开操作308

建议77—1:正确指定fopen的mode参数309

建议77—2:必须检查fopen函数的返回值310

建议77—3:尽量避免重复打开已经被打开的文件311

建议77—4:区别fopen与fopen_s函数312

建议77—5:区别fopen与freopen函数313

建议78:文件操作完成后必须关闭313

建议79:正确理解EOF宏314

建议80:尽量使用feof和ferror检测文件结束和错误316

建议81:尽量使用fgets替换gets函数319

建议82:尽量使用fputs替换puts函数321

建议83:合理选择单个字符读写函数323

建议84:区别格式化读写函数324

建议84—1:区别printf/scanf、fprintf/fscanf和sprintf/sscanf325

建议84—2:尽量使用snprintf替代sprintf函数327

建议84—3:区别vprintf/vscanf、vfprintf/vfscanf、vsprintf/vsscanf和vsnprintf328

建议85:尽量使用fread与fwrite函数来读写二进制文件330

建议86:尽量使用fseek替换rewind函数332

建议87:尽量使用setvbuf替换setbuf函数334

建议88:谨慎remove函数删除已打开的文件336

建议89:谨慎rename函数重命名已经存在的文件337

第10章预处理器338

建议90:谨慎宏定义338

建议90—1:在使用宏定义表达式时必须使用完备的括号339

建议90—2:尽量消除宏的副作用340

建议90—3:避免使用宏创建一种“新语言”342

建议91:合理地选择函数与宏343

建议92:尽量使用内联函数代替宏345

建议93:掌握预定义宏350

建议94:谨慎使用“#include”353

建议94—1:区别“#include<filename.h>”与“#include”filename.h””354

建议94—2:必须保证头文件名称的唯一性355

建议95:掌握条件编译指令355

建议95—1:使用“#ifndef/#define/#endif”防止头文件被重复引用355

建议95—2:使用条件编译指令实现源代码的部分编译357

建议95—3:妙用“defined”358

建议96:尽量避免在一个函数块中单独使用“#define”或“#undef”359

第11章断言与异常处理361

建议97:谨慎使用断言361

建议97—1:尽量利用断言来提高代码的可测试性362

建议97—2:尽量在函数中使用断言来检查参数的合法性367

建议97—3:避免在断言表达式中使用改变环境的语句368

建议97—4:避免使用断言去检查程序错误369

建议97—5:尽量在防错性程序设计中使用断言来进行错误报警370

建议97—6:用断言保证没有定义的特性或功能不被使用372

建议97—7:谨慎使用断言对程序开发环境中的假设进行检查373

建议98:谨慎使用errno374

建议98—1:调用errno之前必须先将其清零375

建议98—2:避免重定义errno377

建议98—3:避免使用errno检查文件流错误379

建议99:谨慎使用函数的返回值来标志函数是否执行成功380

建议100:尽量避免使用goto进行出错跳转380

建议101:尽量避免使用setjmp与longjmp组合381

第12章内存管理384

建议102:浅谈程序的内存结构384

建议103:浅谈堆和栈389

建议104:避免错误分配内存396

建议104—1:对内存分配函数的返回值必须进行检查397

建议104—2:内存资源的分配与释放应该限定在同一模块或者同一抽象层内进行398

建议104—3:必须对内存分配函数的返回指针进行强制类型转换400

建议104—4:确保指针指向一块合法的内存401

建议104—5:确保为对象分配足够的内存空间402

建议104—6:禁止执行零长度的内存分配405

建议104—7:避免大型的堆栈分配405

建议104—8:避免内存分配成功,但并未初始化407

建议105:确保安全释放内存407

建议105—1:malloc等内存分配函数与free必须配对使用407

建议105—2:在free之后必须为指针赋一个新值409

建议106:避免内存越界411

建议106—1:避免数组越界412

建议106—2:避免sprintf、vsprintf、strcpy、strcat与gets越界413

建议106—3:避免memcpy与memset函数长度越界413

建议106—4:避免忽略字符串最后的’\0’字符而导致的越界413

建议107:避免内存泄漏415

建议108:避免calloc参数相乘的值超过size_t表示的范围417

第13章信号处理418

建议109:理解信号418

建议110:尽量使用sigaction替代signal423

建议111:避免在信号处理函数内部访问或修改共享对象428

建议112:避免以递归方式调用raise函数429

第14章了解C11标准432

建议113:谨慎使用_Generic433

建议114:尽量使用gets_s替换gets函数436

建议115:尽量使用带边界检查的字符串操作函数436

建议116:了解C11多线程编程438

建议117:使用静态断言_Static_assert执行编译时检查442

建议118:使用_Noreturn标识不返回值的函数442

第15章保持良好的设计443

建议119:避免错误地变量初始化443

建议120:谨慎使用内联函数444

建议121:避免在函数内定义占用内存很大的局部变量445

建议122:谨慎设计函数参数的顺序和个数446

建议123:谨慎使用标准函数库447

建议124:避免不必要的函数调用447

建议125:谨慎程序中嵌入汇编代码448

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:高性能的C++异步框架 - SeaStar 介绍
下一篇:C++智能指针的基本用法

C语言创建windows窗口实例

C++回调函数是什么?

C++ shared_ptr和动态数组

C语言有哪些关键词,C语言44个关键词大全

  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

  • 搜索抖音号

    搜索抖音号:1821685962

    免费领取达内课程视频学习资料

Copyright © 2021 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省