如何形成一个良好的编程风格(二)

kelly的头像
kelly 发布于:周五, 09/09/2016 - 16:02 ,关键词:

3、标识符

a、变量的命名

方法一:采用匈牙利命名法。命名规则的主要思想是“在变量中加入前缀以增进人们对程序的理解”。

例如平时声明32位整型变量Length对应使用匈牙利命名法为unLength。现在列出经常用到的变量类型。

变量类型 示例

char cLength

unsigned char ucLength

short int sLength

unsigned short int usLength

int nLength

unsigned int unLength

char * szBuf

unsigned char * uszBuf

volatile unsigned char __ucLength

方法二:

Ø 局部变量以小写字母命名;

Ø 全局变量以首字母大写方式命名(骆驼式);

Ø 定义类型和宏定义常数以大写字母命名;

Ø 变量的作用域越大,它的名字所带有的信息就应该越多。

Ø 局部变量: int student_age;

Ø 全局变量: int StudentAge;

Ø 宏定义常数:#define STUDENT_NUM 10

Ø 类型定义: typedef INT16S int;

(我个人喜欢第二种方法)

b、 变量命名要注意缩写而且让人简单易懂,若是特别缩写要详细说明。

经常用到的缩写如:

Count 可缩写为Cnt

Message 可缩写为Msg

Packet 可缩写为Pkt

Temp 可缩写为Tmp

平时不经常用到的缩写,要注释:

SerialCommunication 可缩写为SrlComm //串口通信变量

SerialCommunicationStatus 可缩写为SrlCommStat //串口通信状态变量

c、全局变量和全局函数的命名一定要详细,不惜多用几个单词,例如函数UARTPrintfStringForLCD,

因为它们在整个项目的许多源文件中都会用到,必须让使用者明确这个变量或函数是干什么用的。局部变量和只在一个源文件中调用的内部函数的命名可以。简略一些,但不能太短,不要使用单个字母做变量名,只有一个例外:用i、j 、k 做循环变量是可以的。

d、用于编译开关的文件头,必须加上当前文件名称,防止编译时产生冲突。

例如在UARTInterface.h 头文件中,必须加上以下内容

#ifndef __UARTINTERFACE_H__

#define __UARTINTERFACE_H__

extern void UARTPrintfString(CONST INT8* str);

extern void UARTSendNBytes(UINT8 *ucSendBytes,UINT8 ucLen);

…… //其他外部声明的代码

#endif

e、禁止用汉语拼音作为标识符名称,可读性极差。呵呵。

f、 建议名称间的区别要显而易见。使用标识符名称要注意的一个相关问题是发生在名称之间只有一个字符或少数字符不同的情况,特别是名称比较长时,当名称间的区别很容易被误读时问题就比较显著,比如1(数字1)和l(L 的小写)、0 和O、2 和Z、5 和S,或者n 和h。

4、表达式和基本语句

a、不要编写太复杂的复合表达式;

例如:

i = a >= b && c < d && c + f <= g + h; //复合表达式过于复杂

b、不要有多用途的复合表达式;

例如:

d = (a = b + c) + r ; //应拆分为两个语句:

a = b + c;

d = a + r;

c、如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。

例如:

if(a | b && a & c) //不良的风格

if((a | b) && (a & c)) //良好的风格

注意:只需记住加减运算的优先级低于乘除运算,其它地方一律加上括号。

d、 if 语句

d.a 布尔变量与零值比较

不可将布尔变量直接与TRUE、FALSE 或者1、0 进行比较。

根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE 定义为1,而Visual Basic 则将TRUE 定义为-1。

例:假设布尔变量名字为flag,它与零值比较的标准if 语句如下:

if (flag) // 表示flag为真时满足条件

if (!flag) // 表示flag为假时满足条件

其它的用法都属于不良风格,例如:

if (flag == TRUE)

if (flag == 1 )

if (flag == FALSE)

if (flag == 0)

d.b 整型变量与零值比较

应当将整型变量用“==”或“!=”直接与0比较。

例:假设整型变量为value,它与零值比较的标准if 语句如下:

if (value == 0)

if (value != 0)

不可模仿布尔变量的风格而写成

if (value) // 会让人误解 value 是布尔变量

if (!value)

小技巧:想必大家都有过将赋值操作符“=”当作比较相等操作符“==”用过,这个错误比较的隐晦,不易排查,而且编译器从不把这类事情当作是程序员犯下的错。避免的方法有两种,一种是养成良好的编程习惯,在比较数值时小心翼翼的处理;另一种方法见下面给出的代码:

if (NULL = = p)

{

……

}

是不是觉得这种书写方式很古怪?不是程序写错了?

当然不是!

有经验的程序员为了防止将 if (p = = NULL) 误写成 if (p = NULL),而有意把p 和NULL 颠倒。编译器认为 if (p = NULL) 是合法的,但是会指出 if (NULL = p)是错误的,因为NULL不能被赋值。所以,再次遇到判断整型变量是否与某个数相等时,请这样写吧:

if(2==flag)

{

……

}

d.c 浮点变量与零值比较

不可将浮点变量用“==”或“!=”与任何数字比较。

千万要留意,无论float 还是double 类型变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。

假设浮点变量的名字为x,应当将

if (x == 0.0) // 隐含错误的比较

转化为

if ((x>=-EPSINON) && (x<=EPSINON)) //EPSINON 是精度

5、杂项

a. 一些常量(如圆周率PI)或者常需要在调试时修改的参数最好用#define定义,但要注意宏定义只是简单的替换,因此有些括号不可少。

b. 不要轻易调用某些库函数,因为有些库函数代码很长(我是反对使用printf之类的库函数的,但是是一家之言,并不勉强各位)。

c. 对各运算符的优先级有所了解,记不得没关系,加括号就是,千万不要自作聪明说自己记得很牢。

d. 不管有没有无效分支,switch函数一定要defaut这个分支。一来让阅读者知道程序员并没有遗忘default,并且防止程序运行过程中出现的意外(健壮性)。

e. 函数的参数和返回值没有的话最好使用void。

f. 一些常数和表格之类的应该放到code中去以节省RAM。

g. 程序编完编译看有多少code多少data,注意不要使堆栈为难。

h. 减少函数本身或函数间的递归调用

i. 编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。

j. 在多重循环中,应将最忙的循环放在最内层

k. 避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。

l. 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。

m. 编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。

文章来源: 博客园

围观 535