公司自用的C语言编程规范

    1. 内容布局

【规则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】文件名统一使用小写。

    1. 注释要求

【规则2-1】 C语言的注释符为“/* … */”。C++语言中,多行注释采用“/* … */”,单行注释采用“/*”和“*/”。

 

【规则2-2】一般情况下,源程序有效注释量必须在20%以上。

正例void Main()

{

if (…) /* 条件说明 */

{  /*  简单介绍本复合语句的处理过程  */

     while (…) /* 条件说明 */

{  /*  简单介绍本复合语句的处理过程  */

}  /* end while (条件说明) */   

}  /* end of if (条件说明) */         

}                                                      

【规则2-3】代码宽度不超过120列;函数体有效长度不超过200行,如果超过需要在函数头注释中特别说明原因。

 

【规则2-4】保证代码和注释的一致性。修改代码同时修改相应的注释,不再有用的注释要删除。

 

【规则2-5】在处理变更时,必须在修改代码的地方注明变更单号和修改者.

 

 

    1. 命名规则

【规则3-1】程序中不要出现仅靠大小写区分的相似的命名。

 

【规则3-2】使用一致的前缀来区分变量的作用域,使用一致的小写类型指示符作为前缀来区分变量的类型属性。

说明:变量定义:[作用域_][属性]<变量命名>

[作用域]:                      [属性]:  

    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等,除非逻辑上的确需要编号。

 

 

    1. 变量、常量与类型

【规则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位有符号数

 

    1. 表达式规则

【规则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)

 

 

    1. 函数使用

【规则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类型的函数中每个出口分支都要有返回值.

 

 

 

    1. 资源使用

【规则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等。

 

    1. 指针和数组规则

【规则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);

 

 

    1. 可测试要求

【规则9-1】在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码(如打印函数等)。

 

    1. 断言与错误处理

【规则10-1】整个软件系统应该采用统一的断言。不允许直接使用系统提供的assert,只能使用支撑提供的OSS_ASSERT,并且进行错误处理。对较复杂的断言加上明确的注释。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章