首页>参考读物>计算机科学与技术>软件与程序设计

编写高质量代码:改善C程序代码的125个建议
作者 : 马伟 著
丛书名 : Effective系列丛书
出版日期 : 2016-01-11
ISBN : 978-7-111-52434-2
定价 : 89.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 465
开本 : 16
原书名 :
原出版社:
属性分类: 店面
包含CD :
绝版 : 未绝版
图书简介

本书是华章“编写高质量代码”系列的第7本,之前已经出版C++、C#、Java、Python、Objective-C、JavaScript相关著作。
在通往“C语言技术殿堂”的路上,本书将为你编写健壮、优雅、高质量的C代码指点迷津!内容全部由C编码的最佳实践组成,从C语言语法和C11标准2个方面深入探讨了编写高质量C代码的技巧与禁忌,一共总结出125条宝贵的建议。每一个建议对应C程序员可能会遇到的一类问题,不仅以建议的方式从正反两面给出了被实践证明为十分优秀的解决方案和非常糟糕的解决方案,而且还分析了问题产生的根源,犹如醍醐灌顶,让人豁然开朗。
本书针对每个问题所选择的应用场景都非常典型,给出的建议也都与实践紧密结合。书中的每一条建议都可能在你的下一行代码、下一个应用或下一个项目中崭露头角,建议你将此书搁置在手边,随时查阅,一定能使你的学习和开发工作事半功倍。

图书特色

10余年开发经验的资深C语言专家全面从C语法和C11标准两大方面深入探讨编写高质量C代码的技巧、禁忌和最佳实践

C语言因为既具有高级语言特性,又具有汇编语言特性,所以它是近二十几年来使用最为广泛、生命力最强的编程语言。无论是操作系统、嵌入式系统、普通应用软件,还是移动智能设备开发,它都能够很好地胜任,是公认的最强大的语言。但是,它也是广大程序员认为最难的一门语言,大多数人都停留在“入门”阶段。作为一位C程序员,如何才能编写出健壮、优雅、高质量的代码?本书作者结合自己在该领域十几年的钻研和实践,从以下几个大的方面梳理了经常困扰“入门者”的几大类问题:
基础数据类型问题:如数据取值范围、整数溢出与回绕、浮点数精度、数据类型转换的范围检查等;
数组与指针问题:指针与地址、野指针、空(null)指针、NULL指针、void指针、多级指针、指针函数与函数指针、数组越界与缓冲区溢出等;
内存管理问题:内存分配、内存释放、内存越界与内存泄漏等;
字符与字符串问题:串拷贝与内存拷贝、内存重叠与溢出、字符串查找等;
高效设计问题:表达式设计、算法设计与函数设计、内联函数与宏的取舍等;
其他杂项问题:信号处理、文件系统、断言与异常处理、内嵌汇编的使用等。

作者简介
马 伟
现任华康移动医疗技术总监,资深软件开发专家和架构师,微软最有价值专家(MVP)。拥有10余年软件研发和研发管理经验,擅长C、C++、.NET、Java等编程技术,专注于互联网应用的高性能架构设计与大数据挖掘,推崇互联网开源文化。
畅销IT技术书籍作家,著有《易学C#》和《ASP.NET 4权威指南》等畅销书,同时在大陆和中国台湾两地发行,广受读者好评。

内容简介
本书是华章“编写高质量代码”系列的第7本,之前已经出版C++、C#、Java、Python、Objective-C、JavaScript相关著作。
在通往“C语言技术殿堂”的路上,本书将为你编写出健壮、优雅、高质量的C代码指点迷津!内容全部由C编码的最佳实践组成,从C语言语法和C11标准2个方面深入探讨了编写高质量C代码的技巧与禁忌,一共总结出125条宝贵的建议。每一个建议对应C程序员可能会遇到的一类问题,不仅以建议的方式从正反两面给出了被实践证明为十分优秀的解决方案和非常糟糕的解决方案,还分析了问题产生的根源,犹如醍醐灌顶,让人豁然开朗。
本书针对每个问题所选择的应用场景都非常典型,给出的建议也都与实践紧密结合。书中的每一条建议都可能在你的下一行代码、下一个应用或下一个项目中崭露头角,建议你将此书搁置在手边,随时查阅,一定能使你的学习和开发工作事半功倍。

图书前言

为什么写作本书
众所周知,C语言是一门既具有高级语言特点,又有汇编语言特点的通用计算机编程语言,无论是操作系统(如Microsoft Windows、Mac OS X、Linux和UNIX等)、嵌入式系统与普通应用软件,还是目前流行的移动智能设备开发,随处都可以看见它依然矫健的身影。它能够轻松地应用于各类层次的开发中,从设备驱动程序和操作系统组件到大规模应用程序,它都能够很好地胜任。毋庸置疑,它是二十几年来使用最为广泛、生命力最强的编程语言,它的设计思想也影响了众多后来的编程语言,例如C++、Objective-C、Java、C#等。
尽管C语言有着悠久的历史和广泛的使用场景,但它依旧让大部分计算机编程人员望而生畏,相信绝大多数读者也还停留在“入门者”这个阶段。所谓“入门者”指的是已经可以简单使用C语言编写普通应用程序,但是却不明白如何编写高质量代码的人。面对这样的实际情况,在准备编写本书之前,一连串的问题深深地映入笔者的脑海:到底什么样的编程书籍才能够帮助“入门者”快速进阶?面对市面上众多的优秀C语言编程书籍,编写本书的价值何在?怎样的内容才能够与众不同?
带着这一连串的问题,笔者开始回顾自己这些年的开发生涯,发现如下几类问题经常困扰“入门者”:
基础数据类型问题:如数据取值范围、整数溢出与回绕、浮点数精度、数据类型转换的范围检查等。
数组与指针问题:指针与地址、野指针、空(null)指针、NULL指针、void指针、多级指针、指针函数与函数指针,以及数组越界与缓冲区溢出等。
内存管理问题:内存分配、内存释放、内存越界与内存泄漏等。
字符与字符串问题:串拷贝与内存拷贝,内存重叠与溢出,字符串查找等。
高效设计问题:表达式设计、算法设计与函数设计,内联函数与宏的取舍等。
其他杂项问题:信号处理、文件系统、断言与异常处理、内嵌汇编的使用等。
如果你同样也苦于处理这些问题,或者对这些问题模棱两可,那么本书正是为你所准备的。本书为普遍存在于初级与中级开发者脑海中的那些问题给出了经验性的解决方案。全书分为15章,通过125个建议深度剖析C语言程序设计中的常见性问题,并给出经验性的解决方案。除此之外,为了使读者能够尽量做到“知其所以然”,本书重点阐述了一些尖锐的问题,如IEEE 754浮点数、指针与数组、越界与溢出等问题。当然,这些经验和心得的积累并非我一人之力,“我只不过是站在巨人的肩膀上而已”。因此,在撰写本书的过程中也参考了大量的资料,如www.securecoding.cert.org的《SEI CERT C Coding Standard》、ISO/IEC 9899:1990、ISO/IEC 9899:1999与ISO/IEC 9899:201x标准文档等。
如何阅读本书
本书适合那些有一定C语言基础并希望快速提升程序设计能力的初级与中级程序员。因此,本书并不会阐述C语言中的一些基础概念,而是将C语言编程过程中可能遇到的疑问或者障碍进行一一列举与剖析,并给出了经验性解决方案与建议。
如果你是一位有一定C语言编程基础的初中级读者,本书就是为你量身打造的。你可以逐章进行系统性学习,并结合我们提供的源码动手实践,巩固所学的知识。书中的大多数建议实战性很强,要完全理解其中的奥妙,请果断地放弃printf函数,多调试一下程序,编程高手都是调试出来的;如果你是一位编程经验非常丰富的高级读者,那么可以将书中的大部分经验与自己的一些经验进行融合,从而获得更多提高与升华。
资源及勘误
通常情况下,一个问题的解决方案往往不止一种,你可能会不同意本书中的一些观点,甚至强烈反对。同时,尽管笔者在本书的写作过程中非常认真与努力,但由于水平有限,书中难免存在错误和不足之处,恳请批评指正。如果你对本书有什么意见、问题或想法,欢迎使用下面的邮箱通知笔者,笔者将不胜感激。当然,也可以通过微信(sc-mawei)与笔者取得联系,共同进行技术交流。
Email:madengwei@hotmail.com
特别鸣谢
最后,要感谢那些所有帮助过笔者的人,没有他们的帮助与付出,这本书很难顺利完成。尤其要感谢下面这些人:
首先,机械工业出版社的杨福川与姜影为本书的整体策划、审阅和出版做了大量的工作,与他们的合作是非常愉快的。同时,由于写作过程漫长,难免令笔者情绪波动,是他们给了我一如既往的支持与鼓励,当我想要放弃的时候,是他们的敦促让我对写作时刻保持着热情,坚持完成本书。也正因为他们对本书的不断要求,才使得本书的结构更加系统化,内容更加深刻,语言更加简单易懂。
其次,要感谢家人的支持。为了编写本书,笔者投入了大量的时间和精力,牺牲了许多可以陪家人的周末和节假日。
最后,要感谢那些曾经为本书的编写提过意见的朋友,感谢他们对本书的默默支持。

马 伟

上架指导

计算机\程序设计

封底文字

C语言因为既具有高级语言特性,又具有汇编语言特性,所以它是近二十几年来使用最为广泛、生命力最强的编程语言。无论是操作系统、嵌入式系统、普通应用软件,还是移动智能设备开发,它都能够很好地胜任,是公认的最强大的语言。但是,它也是广大程序员认为最难的一门语言,大多数人都停留在“入门”阶段。作为一位C程序员,如何才能编写出健壮、优雅、高质量的代码?本书作者结合自己在该领域十几年的钻研和实践,从以下几个大的方面梳理了经常困扰“入门者”的几大类问题:
? 基础数据类型问题:如数据取值范围、整数溢出与回绕、浮点数精度、数据类型转换的范围检查等;
? 数组与指针问题:指针与地址、野指针、空(null)指针、NULL指针、void指针、多级指针、指针函数与函数指针,数组越界与缓冲区溢出等;
? 内存管理问题:内存分配、内存释放、内存越界与内存泄漏等;
? 字符与字符串问题:串拷贝与内存拷贝,内存重叠与溢出,字符串查找等;
? 高效设计问题:表达式设计、算法设计与函数设计,内联函数与宏的取舍等;
? 其他杂项问题:信号处理、文件系统、断言与异常处理、内嵌汇编的使用等。

作者简介

马伟 著:马伟 微软公司最有影响力的开发者之一,资深微软技术专家,软件研发工程师与系统分析师。在其以往的程序岁月中,曾经负责过远程视频监控系统、视频营销平台、企业管理应用系统、南方电网四分统计平台等项目的架构设计与开发。擅长系统分析、架构设计、数据库设计与实现、设计模式、SOA等技术,尤其对C#与UML、C++与UML的架构设计与编程有独到的见解。

图书目录

前 言
第1章 数据,程序设计之根本 1
建议1:认识ANSI C 1
建议2:防止整数类型产生回绕与溢出 6
建议2-1:char类型变量的值应该限制在signed char与unsigned char的交集范围内 11
建议2-2:使用显式声明为signed char或unsigned char的类型来执行算术运算 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:了解IEEE 754浮点数 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不同于#define 65
建议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:避免“悬挂”的else 102
建议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:区别“const int *p”与“int *const p” 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与内存拷贝memcpy 270
建议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/sscanf 325
建议84-2:尽量使用snprintf替代sprintf函数 327
建议84-3:区别vprintf/vscanf、vfprintf/vfscanf 、vsprintf/vsscanf和vsnprintf 328
建议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 ”与“#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:谨慎使用errno 374
建议98-1:调用errno之前必须先将其清零 375
建议98-2:避免重定义errno 377
建议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替代signal 423
建议111:避免在信号处理函数内部访问或修改共享对象 428
建议112:避免以递归方式调用raise函数 429
第14章 了解C11标准 432
建议113:谨慎使用_Generic 433
建议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

教学资源推荐
作者: 顾治华 陈天煌 孙珊珊 编著
作者: [美] 罗伯特·W. 塞巴斯塔(Robert W. Sebesta) 著
参考读物推荐
作者: 王国辉 李伟 等编著
作者: Dharma Shukla;Bob Schmidt
作者: (美) Bruce Powel Douglass 著