研发中心编码规范

第一条 编码规范目的
     1.合理的规范可以减少后期开发人员对代码的维护;
    2.编码规范可以改善软件的可读性,可以让程序员尽快而彻底地理解新的代码。为了执行规范,每个开发人员必须一致遵守编码规范;
    3.使用统一编码规范的主要原因,是使应用程序的结构和编码风格标准化,以便于阅读和理解这段代码;
    4.好的编码约定可使源代码严谨、可读性强且意义清楚,与其它语言约定相一致,并且尽可能的直观。

第二条 适用范围
研发中心全体研发人员。

第三条 规范内容

1.不要使用难懂的技巧性很高的语句,除非很有必要时
高技巧语句不等于高效率的程序,实际上程序的效率关键在于算法。这可能是很多初学者最容易犯得错误。

2.去掉没必要的公共变量
公共变量是增大模块间耦合的原因之一。全局变量虽然好用,但是宜少不宜多这样能保证数据的安全性。

3.当向公共变量传递数据时,最好做数据合法性检查。
有必要最好做一下,因为万一出了问题是不好检测出来。

4.构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象还是前面讲到的数据安全性问题,可以通过静态函数实现,且整个系统都要保持一致。

5.仔细设计结构中元素的布局与排列顺序, 使结构容易理解、节省占用空间,并减少引起误用现象。
   示例:如下结构中的位域排列,将占较大空间,可读性也稍差。

typedef struct EXAMPLE_STRU
{
unsigned int valid: 1;
PERSON person;
unsigned int set_flg: 1;
} EXAMPLE;
若改成如下形式,不仅可节省 1 字节空间,可读性也变好了。
typedef struct EXAMPLE_STRU
{
unsigned int valid: 1;
unsigned int set_flg: 1;
PERSON person ;
} EXAMPLE;

6.尽量减少没有必要的数据类型默认转换与强制转换。

7.对所调用函数的错误返回码要仔细、全面地处理Linux系统里好像是不允许有空函数的。

8.防止将函数的参数作为工作变量
将函数的参数作为工作变量, 有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。
    示例:下函数的实现不太好。
 

void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count;
*sum = 0;
for (count = 0; count < num; count++)
{
*sum += data[count]; // sum 成了工作变量,不太好。
}
}


若改为如下,则更好些。

void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count ;
int sum_temp;
sum_temp = 0;
for (count = 0; count < num; count ++)
{
sum_temp += data[count];
}
*sum = sum_temp;
}

9.一个函数仅完成一件功能。

10.避免设计多参数函数,不使用的参数从接口中去掉。目的减少函数间接口的复杂度,参数多的话可以通过结构体实现。

11.非调度函数应减少或防止控制参数,尽量只使用数据参数,避免函数功能不明确,给调试带来麻烦
    示例:如下函数构造不太合理。

int add_sub( int a, int b, unsigned char add_sub_flg )
{
if (add_sub_flg == INTEGER_ADD)
{
return (a + b);
}
else
{
return (a ٛ b);
}
}
不如分为如下两个函数清晰。
int add( int a, int b )
{
return (a + b);
}
int sub( int a, int b )
{
return (a ٛ b);
}

12.检查函数所有参数输入的有效性
功能不明确较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上级函数中,而不必单独存在。

13.设计高扇入、合理扇出(小于7)的函数。
函数较合理的扇出(调度函数除外) 通常是 3-5.较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。还是强调函数的高复用性和可读性。

14.避免使用BOOL参数
TURE/FALSE 的含义是非常模糊的,这点确实有点惊讶,对于那些内存要求不是很苛刻的能不用就不用吧。

15.对于提供了返回值的函数,在引用时最好使用其返回值。

16.当一个变量名较长且有较多引用时(一般是结构的成员), 可以用一个意义相当的宏代替也可以定义一个局部变量,在用之前对局部变量赋值。

17.在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号行号和文件名可以用宏__LINE__和__FILE__实现

18.使用断言来发现软件问题, 提高代码可测性。
断言可以对在系统中隐藏很深,用其它手段极难发现的问题进行定位。
    示例:下面是 C 语言中的一个断言,用宏来设计的。(其中 NULL 为 0L)

#ifdef _EXAM_ASSERT_TEST_ // 若使用断言测试
void exam_assert( char * file_name, unsigned int line_no )
{
printf( "\n[EXAM]Assert failed: %s, line %u\n",
file_name, line_no );
abort( );
}
#define EXAM_ASSERT( condition )
if (condition) // 若条件成立,则无动作
NULL;
else // 否则报告
exam_assert( __FILE__, __LINE__ )
#else // 若不使用断言测试
#define EXAM_ASSERT(condition) NULL
#endif /* end of ASSERT */

19.在编写代码之前, 应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等。

20.在保证软件系统的正确性、 稳定性、可读性及可测性的前提下,提高代码效率。

21.避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中笔者确实踩过这样的坑,并且真的很难发现是什么问题。另外循环嵌套尽量不要超过三层且不要太复杂。

22.尽量用乘法或其它方法代替除法,特别是浮点运算中的除法,浮点运算除法要占用较多 CPU 资源,应为一般的cpu只有硬件乘法器。

23.过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭。分配的内存不释放以及文件句柄不关闭,是较常见的错误,而且稍不注意就有可能发生。这类错误往往会引起很严重后果,且难以定位。

24.有可能的话, if语句尽量加上else分支,对没有else分支的语句要小心对待; switch语句必须有default分支。

25.时刻注意表达式是否会上溢、下溢。
示例:如下程序将造成变量下溢。

unsigned char size ;
while (size-- >= 0) // 将出现下溢
{
... // program code
}

26.打开编译器的所有警告开关对程序进行编译。

27.某些语句经编译后产生警告,但如果你认为它是正确的,那么应通过某种手段去掉告警信息。
    示例:

#pragma warn -rvl // 关闭告警
int examples_fun( void )
{
// 程序,但无 return 语句。
}
#pragma warn +rvl // 打开告警

28.使用代码检查工具(如C语言用PC-Lint)对源程序检查。使用软件工具(如 LogiSCOPE)进行代码审查用过其中一个,效果不理想可能是不会用吧。

29.不应通过“试” 来解决问题。应寻找问题的根本原因,
最精辟的原则之一,而非通过“试”来解决出现的问题。

30.对自动消失的错误进行分析,搞清楚错误是如何消失的。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐