【规则1-1】遵循统一的布局顺序来书写头文件。 |
说明:以下内容如果某些节不需要,可以忽略。但是其它节要保持该次序。
文件注释
#ifndef 文件名_H(全大写)
#define 文件名_H
其它预编译条件选项
#include(依次为标准库头文件、非标准库头文件)
常量和全局宏定义全局宏
全局数据类型
全局变量声明(extern)
全局函数原型
#endif
【规则1-2】遵循统一的布局顺序来书写实现文件。 |
说明:以下内容如果某些节不需要,可以忽略。但是其它节要保持该次序。
文件注释
#include(依次为标准库头文件、非标准库头文件)
常量定义和文件内部使用宏的定义
文件内部使用的数据类型
全局变量定义和声明(extern) /*不允许在新增加的实现文件中使用全局变量extern声明 */
静态全局变量
全局函数声明(extern)/*不允许在新增加的实现文件中使用全局函数extern声明 */
局部函数原型
全局函数实现
局部函数实现
【规则1-3】禁止使用TAB键,必须使用空格进行缩进。嵌套的条件编译采用缩进的格式,{ }之内的代码块使用缩进规则对齐。缩进为4个空格。 |
【规则1-4】if、else、else if、for、while、do、switch、case等所有条件和循环控制语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 “{”、“ }”,“{”和“}”必须各占一行。 |
正例:if (ucVal < ucIndexMax)
{
ucVal = ucIndexMax;
}
反例:if (ucVal < ucIndexMax) ucVal = ucIndexMax;
【规则1-5】定义指针类型的变量,*应放在变量前。 |
正例:float *pfBuffer = NULL;
反例:float* pfBuffer;
【规则1-6】文件名统一使用小写。 |
-
- 注释要求
【规则2-1】 C语言的注释符为“/* … */”。C++语言中,多行注释采用“/* … */”,单行注释采用“/*”和“*/”。 |
|
【规则2-2】一般情况下,源程序有效注释量必须在20%以上。 |
正例:void Main()
{
if (…) /* 条件说明 */
{ /* 简单介绍本复合语句的处理过程 */
while (…) /* 条件说明 */
{ /* 简单介绍本复合语句的处理过程 */
…
} /* end while (条件说明) */
…
} /* end of if (条件说明) */
【规则2-3】代码宽度不超过120列;函数体有效长度不超过200行,如果超过需要在函数头注释中特别说明原因。 |
【规则2-4】保证代码和注释的一致性。修改代码同时修改相应的注释,不再有用的注释要删除。 |
【规则2-5】在处理变更时,必须在修改代码的地方注明变更单号和修改者. |
【规则3-1】程序中不要出现仅靠大小写区分的相似的命名。 |
说明:变量定义:[作用域_][属性]<变量命名>
[作用域]: [属性]:
g_ : 全局变量 uc : unsigned char 或 byte
s_ : 静态变量 c : char
空 : 局部变量 w : 16位无符号数
sw : 16位有符号数
dw : 32位无符号数
sdw : 32位有符号数
qw : 64位无符号数
sqw : 64位有符号数
f : 浮点数;
p : pointer
a : 数组,array of TYPE
str : 字符串
t : 结构类型,枚举,联合
以上前缀可以进一步组合,在进行组合时,数组和指针类型的前缀指示符必须放在变量类型前缀的首位。
【规则3-3】结构类型名、联合类型名、枚举类型名由后缀 _T 结尾。 |
【规则3-4】程序中局部变量不要与全局变量重名。 |
【规则3-5】尽量避免名字中出现数字编号,如Value1、Value2等,除非逻辑上的确需要编号。 |
【规则4-1】一个变量有且只有一个功能,不能把一个变量用作多种用途。 |
【规则4-2】宏定义中如果包含表达式或变量,表达式和变量必须用小括号括起来。 |
正例:#define HANDLE(A, B) (( A ) / ( B ))
反例:#define HANDLE(A, B) (A / B)
【规则4-3】使用宏定义多行语句时, 必须使用 { } 把这些语句括起来。 |
【规则4-4】实现代码中不允许使用数值,所有用到的地方必须用宏代替. |
【规则4-5】模块间接口如果使用简单类型定义,则必须使用经过统一封装定义后的BYTE,CHAR, WORD16,SWORD16,WORD32,SWORD32,WORD64,SWORD64等数据类型。在能够使用自定义数据类型实现的前提下,禁止直接使用C语言提供的原始数据类型,如char,int,long,bool等。 |
说明:BYTE 8位无符号数 WORD16 16位无符号数
CHAR 8位有符号数 SWORD16 16位有符号数
WORD32 32位无符号数 WORD64 64位无符号数
SWORD32 32位有符号数 SWORD64 64位有符号数
【规则5-1】在表达式中使用括号和排版,使表达式的运算顺序更清晰。 |
正例:if( ( (dwYear % 4 == 0) && (dwYear % 100 != 0) )
|| (dwYear % 400 == 0) )
【规则5-2】避免表达式中的附加功能,不要编写太复杂的复合表达式。 |
反例1:
dwResult = (adwVar[1]=adwVar[2]++);/* 附加功能:对adwVar[1]赋值,adwVar[2]自增 */
反例2:
c = (a > b) ? a : b;
【规则5-3】不可将浮点变量用“==”或“!=”与任何数字比较。 |
|
【规则5-4】在switch语句中,每一个case后面如果相应功能实现代码,分支必须使用break,最后一个分支必须是default分支。 |
反例:
switch( dat->thisState )
{
case EV_MASTER_POWER_ON:
proxyInitialize(&proxyData);
case EV_DRDYNCONFIG_NOTIFY:
mhdOnHsdbSwitchEvent(&dat,req);
break;
default:
break;
}
【规则5-5】不可在for 循环体内修改循环控制变量,防止for 循环失去控制。 |
【规则5-6】进行“==”比较时,将常量或常数放在“==”号的左边。 |
正例:if (NULL == ptTail)
【规则6-1】本模块向其它模块提供的接口函数中,需要对输入参数的正确性和有效性进行检查。 |
【规则6-2】禁止改写函数的入参。 |
【规则6-3】一个函数的参数之和不要超过5个。 |
【规则6-4】无论是函数或者宏函数,在使用过程中,传递进来的参数要求是变量或者常量,不要涉及表达式。 |
反例:#define OPERAND(a) ( (a) + (a) )
OPERAND(i++); /* 这条语句在实现中i其实被增加了两次,增加了潜在的错误 */
【规则6-5】必须对所调用函数的错误返回值进行处理。 |
【规则6-6】一个函数内定义的局部变量的大小总和不允许超过1K,特殊情况需要说明原因。 |
【规则6-7】非void类型的函数中每个出口分支都要有返回值. |
【规则7-1】对数组、指针、内存地址等的操作,必须注意被操作内存的大小和边界是否合适,防止内存操作读取和写入越界。要求先比较源和目的大小,然后取值小的进行操作。当OSS提供封装后的内存操作函数后,要求使用封装的函数。 |
正例:
CHAR acName[NAME_SIZE];
CHAR acOtherName[OTHER_NAME_SIZE];
if(OTHER_NAME_SIZE>NAME_SIZE )
{
memcpy(acName, acOtherName,NAME_SIZE );
}
else
{
memcpy(acName, acOtherName,OTHER_NAME_SIZE );
}
反例:
CHAR acName[NAME_SIZE];
CHAR acOtherName[OTHER_NAME_SIZE];
memcpy(acName, acOtherName,NAME_SIZE );
【规则7-3】不要忘记字符串包含一个终止符号”\0”,而该符号会占用一个内存空间,但是strlen统计的长度并没有将之包含在内。 |
【规则7-4】字符串操作要求使用带长度限制的接口,比如字符串拷贝规定使用strncpy、 strncat等,禁止使用strcpy、 strcat等,字符串格式化使用snprintf或_snprintf,禁止使用sprintf等。 |
【规则8-1】指针类型变量必须初始化(NULL或者其它确定的值)。 |
【规则8-2】如果变量明确不会被修改,应该增加const属性,以加强编译器的检查。 |
【规则8-3】对指针进行算术操作必须有明确注释。 |
正例: WORD16 *pwMsg = NULL;
……
pwMsg += 5; /* 向前偏移5个元素,共10个字节 */
【规则8-4】禁止对数组名进行算术运算访问数组元素,规定使用数组名和数组下标(所有维数)访问数组元素。 |
反例:int aucBuf[10],ucVal;
ucVal = *(aucBuf+1);
正例 :
int aucBuf[10],ucVal;
ucVal= aucBuf[1]
【规则8-5】对指针的操作要求使用括号括起来以明确代码的语义。 |
反例:
WORD *pwSize=NULL ;
WORD wLen = 0 ;
wLen=*pwSize+1;
正例:
WORD *pwSize=NULL ;
WORD wLen = 0 ;
wLen=*(pwSize+1);
【规则9-1】在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码(如打印函数等)。 |
【规则10-1】整个软件系统应该采用统一的断言。不允许直接使用系统提供的assert,只能使用支撑提供的OSS_ASSERT,并且进行错误处理。对较复杂的断言加上明确的注释。 |