1- 避免操作符混淆
在C语言中,有些操作符很相似,比如=与==、|与||、&与&&等。在使用这些操作符时,一不小心就很容易造成混淆,给程序带来不必要的错误。
| :位或 ; ||: 逻辑或
&:位与 ; &&: 逻辑与
1.1- 避免“=”与“==”混淆
错误:
对于和常量比较的条件判断,可以把常量写在前面,避免混淆=和==。
因为当编译类似if (3 = ret )会报错。
// if ( 常量 == 变量 )
if (3 == ret)
{
/* do something */
}
2- 表达式的设计应该兼顾效率与可读性
尽量使用复合赋值运算符
尽量避免编写多用途的、太复杂的复合表达式
尽量避免在表达式中使用默认的优先级
3- 程序控制语句应该保持简洁高效
C语言也提供三种基本流程控制结构:顺序结构、选择结构与循环结构。
3.1- if语句应该尽量保持简洁,减少嵌套的层数
3.2- 先处理正常情况,再处理异常情况
首要原则就是要使正常情况的执行代码清晰,确认那些不常发生的异常情况处理代码不会遮掩正常的执行路径。也就是说,我们应该把正常情况的处理放在if后面,而不要放在else后面。
4- 谨慎0值比较
4.1- 避免布尔型与0或1进行比较
不合适:
订正:
4.2- 整型变量应该直接与0进行比较
if (0 == ret)
4.3- 避免浮点变量用“==”或“!=”与0进行比较
4.4- 指针变量应该用“==”或“!=”与NULL进行比较
if (NULL == pRet)
5- 避免使用嵌套的?:
6- 正确使用for循环
6.1- 尽量使循环控制变量的取值采用半开半闭区间写法
6.2- 避免在循环体内修改循环变量
6.3- 尽量使逻辑判断语句置于循环语句外层
需要注意的是,循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而定。一般情况下,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以
不合适:
订正:
6.4- 尽量将多重循环中最长的循环放在最内层,最短的循环放在最外层
在多重for循环中,如果有可能,应当尽量将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数。
不合适:
订正:
6.5- 尽量将循环嵌套控制在3层以内
7- 适当地使用并行代码来优化for循环(惊呆了!)
尽量把长的有依赖的代码链分解成几个可以在流水线执行单元中并行执行的没有依赖的代码链
修改前:
修改后:
浮点数的精确度问题,在一些情况下,这些优化可能会导致意料之外的结果。但在大部分情况下,最后结果可能只有最低位存在错误。因此,对计算结果正确性的影响不大。
8- 谨慎使用do/while与while循环
8.1- 无限循环优先选用for(;;),而不是while(1) (学到了)
从while和for的语义上来看,显然for(;;)语句运行速度要快一些。
按照for的语法规则,两个分号“;”分开的是3个表达式。现在表达式为空,很自然地被编译成无条件的跳转(即无条件循环,不用判断条件)
while()语句中必须有一个表达式(这里是1)判断条件,生成的代码用它进行条件跳转。即while语句()属于有条件循环。
8.2- 优先使用for循环替代do/while与while循环
for循环的代码相比之下就更易读懂了。当然,如果在循环的次数不明确的情况下,还是要使用do/while和while循环。
9- 正确地使用switch语句
case语句后面只能是整型或字符型的常量或常量表达式;而在if语句中还能够测试关系与逻辑表达式。
9.1- 不要忘记在case语句的结尾添加break语句
9.2- 不要忘记在switch语句的结尾添加default语句(学到了)
switch语句中去掉default语句,那么switch语句将失去对默认情况与错误情况的处理能力。
10- 选择合理的case语句排序方法
尽量按照字母或数字顺序来排列各条case语句
尽量将情况正常的case语句排在最前面
尽量根据发生频率来排列各条case语句
11- 尽量避免使用goto语句
goto会破环代码的结构,可读性变差,但是驱动异常处理、多层嵌套中,提前退出使用goto还是比较合理的。