个人读《编写高质量代码改善C++程序的150个建议》摘录的重点.doc
《个人读《编写高质量代码改善C++程序的150个建议》摘录的重点.doc》由会员分享,可在线阅读,更多相关《个人读《编写高质量代码改善C++程序的150个建议》摘录的重点.doc(6页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、【精品文档】如有侵权,请联系网站删除,仅供学习与交流个人读编写高质量代码改善C+程序的150个建议摘录的重点.精品文档.个人读编写高质量代码:改善C+程序的150个建议摘录的重点 本人主要从事底层驱动的编写,因此主要阅读了编写高质量代码:改善C+程序的150个建议其中的C语言的部分,对于自己认为重要的点记录于此(呵呵,其实每点都重要)1. 不要让main函数写成void main要想保证程序具有良好的可移植性能,就要标明 main 函数返回 int,而不是 void。强烈建议使用以下形式:int main() / some processing codes return 0;2. 赋值符“=”
2、和运算符“= =”的区别下面的代码就是一个典型的例子:if(nValue = 0) / do something if nValue is not zero.显然,程序员的本意是要写 if( nValue = = 0 )。不幸的是,上述语句虽未达成程序员的本意,但它却完全是合法的,编译器不会给出任何错误提示。C+ 语句首先会将 nValue 赋值为0,然后再判断 nValue 是否为非零。结果就是 if 条件始终不能被满足,大括号中的代码永远不会被执行。针对 = 和 = 之间的问题,通过良好的代码习惯可以避免,代码如下所示:if(0 = nValue) / do something if nV
3、alue is not zero.其他几对容易弄错的运算符是 &(按位与)和 &(与) ,以及 |(按位或)和 |(或) 。对于这两对运算符,能够避免错误的只有细心。3. 对表达式计算顺序不要想当然不要过分自信地认为自己已经熟悉了所有运算符的优先级、结合律,多写几个括号确实是个好主意。例如:COLOR rgb = (red16) | (green8) | blue;bool isGradeOne = (nGrade & MASK) = GRADE_ONE);The C Programming Lauguage (程序员亲切地称此书为“K R” )中反复强调,函数参数也好,某个操作符中的操作数也
4、罢,表达式求值次序是不一定的,每个特定机器、操作系统、编译器也都不一样。例如:a = p() + q() * r();三个函数 p()、q() 和 r() 可能以 6 种顺序中的任何一种被评估求值。乘法运算符的高优级只能保证 q() 和 r() 的返回值首先相乘,然后再加到 p() 的返回值上。所以,就算加上再的括号依旧不能解决问题。幸运的是,使用显式的、手工指定的中间变量可以解决这一问题,从而保证固定的子表式评估求值顺序:int para1 = p();int para2 = q();a = para1 + para2 * r();这样,上述代码就为 p()、q() 和 r() 三个函数指定
5、了唯一的计算顺序:p() q() r()。4. 小心宏 #define 使用中的陷阱(1) 用宏定义表达式时,要使用完备的括号。错误的定义:#define ADD( a, b ) a + b#define MULTIPLE( a, b ) (a * b)正确的定义应为:#define ADD( a, b ) (a)+(b)#define MULTIPLE( a, b ) (a)*(b)(2) 使用宏时,不允许参数发生变化。#define SQUARE( a ) (a) * (a)int Square(int a) return a*a;int nValue1 = 10, nValue2 = 1
6、0;int nSquare1 = SQUARE(nValue1+); / nSquare1=110, nValue1=12int nSquare2 = Square(nValue2+);/ nSquare2=100, nValue2=11类似的定义,却产生了不同的结果,究其原因还是宏的字符替换问题。正如上面的示样,两处的 a 都被参数 nValue1+ 替换了,所以 nValue1 自增操作也就被执行了两回。这就是宏在展开时对其参数的多次取值替换所带来的副作用。为了避免出现这样的副作用。最简单有效的方法就是保证宏参数不发生变化,如下所示。#define SQUARE( a ) (a) * (a
7、)int nValue1 = 10;int nSquare1 = SQUARE(nValue1); / nSquare1=100nValue1+; / nValue1=11(3) 用大括号将宏所定义的多条表达式括起来。如果宏定义包含多条表达式,一定要用大括号将其括起来。如果没有这个大括号,宏定义的多条表达式很有可能只有第一句会被执行,正如下面的代码片段: #define CLEAR_CUBE_VALUE( l, w, h ) l = 0; w = 0; h = 0;正确的做法应该是用大括号将多条表达式括起来,这样就能保证多条表达式全部执行了,如下面的代码片段所示:#define CLEAR_C
8、UBE_VALUE( l, w, h ) l = 0; w = 0; h = 0;5. 不要忘记指针变量的初始化指针是 C/C+ 语言编程中最给力的工具。指针,让我们直接去面对最为神秘的内存空间,赋予我们对内存进行直接操作的能力。为对于全局变量来说,在声明的同时,编译器会悄悄完成对变量的初始化。使用未初始化的局部指针变量是件很危险的事,所以,在使用局部指针变量时,一定要及时将其初始化。6. 时刻提防内存溢出在内存空间中,当要表示的数据超出了计算机为该数据分配的空间范围时,就产生了溢出,而溢出的多余数据则可以作为指令在计算机中大摇大摆地运行,这样很容易造成程序崩溃。C 语言中的字符串库没有采用相
9、应的安全保护措施,所以在使用时要特别小心。例如在执行 strcpy、strcat 等函数操作时没有检查缓冲区大小,就会很容易引起安全问题。现在分析下面的代码片段:const int MAX_DATA_LENGTH = 32;void DataCopy (char *szSrcData)char szDestDataMAX_DATA_LENGTH; strcpy(szDestData, szSrcData); /原文这里有笔误strcpy(cDest,szData); / processing codes似乎这段代码不存在什么问题,但是细心的读者还是会发其中的危险。如果数据源szSrcDatar
10、 的长度不超过规定的长度,那么这段代码确实没什么问题。strcpy() 不会在乎数据来源,也不会检查字符串长度,唯一能让它停下来的只有字符串结束符 0。不过,如果没有遇到这个结束符,它就会一个字节一个字节地复制 szSrcData 的内容,在填满 32 字节的预设空间后,溢出的字符就会取代缓冲区后面的数据。如果这些溢出的数据恰好覆盖了后面DataCopy 函数的返回地址,在该函数调用完毕后,程序就会转入攻击者设定的“返回地址”中,乖乖地进入预先设定好的陷阱。为了避免落入这样的圈套,给作恶者留下可乘之机,当 C/C+ 代码处理来自用户的数据时,应该处处留意。如果一个函数的数据来源不可靠,又要用到
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编写高质量代码改善C+程序的150个建议 个人 编写 质量 代码 改善 C+ 程序 150 建议 摘录 重点
限制150内