1、编码规范 1.0 RD2(函数、过程篇) - 1 -函数、过程1:对所调用函数的错误返回码要仔细、全面地处理。(返回值)2:明确函数功能,精确(而不是近似)地实现函数设计。3:编写可重入函数时,应注意局部变量的使用(如编写C/C+ 语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。说明:编写 C/C+语言的可重入函数时,不应使用 static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。4:编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P 、V操作)等手段对其加以保护。说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数
2、时,很有可能使有关全局变量变为不可知状态。示例:假设 Exam是 int型全局变量,函数 Squre_Exam返回 Exam平方值。那么如下函数不具有可重入性。unsigned int example( int para )unsigned int temp;Exam = para; / (*)temp = Square_Exam( );return temp;此函数若被多个进程调用的话,其结果可能是未知的,因为当(*)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使 Exam赋与另一个不同的 para值,所以当编码规范 1.0 RD2(函数、过程
3、篇) - 2 -控制重新回到“temp = Square_Exam( )”后,计算出的 temp很可能不是预想中的结果。此函数应如下改进。unsigned int example( int para )unsigned int temp;申请信号量操作 / 若申请不到“信号量” ,说明另外的进程正处于Exam = para; / 给 Exam赋值并计算其平方过程中(即正在使用此temp = Square_Exam( ); / 信号) ,本进程必须等待其释放信号后,才可继释放信号量操作 / 续执行。若申请到信号,则可继续执行,但其/ 它进程必须等待本进程释放信号量后,才能再使/ 用本信号。ret
4、urn temp;5:在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接口函数本身负责,缺省是由函数调用者负责。(明确,由函数调用者负责合法性检查)说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。6:防止将函数的参数作为工作变量。说明:将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最
5、后再将该局部变量的内容赋给该参数。示例:下函数的实现不太好。void sum_data( unsigned int num, int *data, int *sum )unsigned int count;编码规范 1.0 RD2(函数、过程篇) - 3 -*sum = 0;for (count = 0; count b ) ? a : b ;改为如下就很清晰了。int max (int a, int b)编码规范 1.0 RD2(函数、过程篇) - 4 -return (a b) ? a : b);value = max (a, b);或改为如下。#define MAX (a, b) (a)
6、 (b) ? (a) : (b)value = MAX (a, b);10:不要设计多用途面面俱到的函数。说明:多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难。11:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出。说明:带有内部“存储器”的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在 C/C+语言中,函数的 static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是 STATIC的局部变量的地址作为返回值,若为AUTO类,则
7、返回为错针。示例:如下函数,其返回值(即功能)是不可预测的。unsigned int integer_sum( unsigned int base )unsigned int index;static unsigned int sum = 0; / 注意,是 static类型的。/ 若改为 auto类型,则函数即变为可预测。for (index = 1; index B-C-A) ,影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间) ;递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。30:仔细分析模块的功能及性能需求,并进一步细分,同时若
8、有必要画出有关数据流图,据此来进行模块的函数划分与组织。说明:函数的划分与组织是模块的实现过程中很关键的步骤,如何划分出合理的函数结构,关系到模块的最终效率和可维护性、可测性等。根据模块的功能图或/ 及数据流图映射出函数结构是常用方法之一。31:改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性。优化函数结构时,要遵守以下原则:(1)不能影响模块功能的实现。(2)仔细考查模块或函数出错处理及模块的性能要求并进行完善。(3)通过分解或合并函数来改进软件结构。(4)考查函数的规模,过大的要进行分解。(5)降低函数间接口的复杂度。(6)不同层次的函数调用要有较
9、合理的扇入、扇出。编码规范 1.0 RD2(函数、过程篇) - 10 -(7)函数功能应可预测。(8)提高函数内聚。 (单一功能的函数内聚最高)说明:对初步划分后的函数结构应进行改进、优化,使之更为合理。32:在多任务操作系统的环境下编程,要注意函数可重入性的构造。说明:可重入性是指函数可以被多个任务进程调用。Sysol2 和 Sysol3 平台是多任务并行结构,所以要注意函数的重入,避免造成冲突。33:尽量避免使用 BOOL参数。说明:原因有二,其一是 BOOL参数值无意义,TURE/FALSE 的含义是非常模糊的,在调用时很难知道该参数到底传达的是什么意思;其二是BOOL参数值不利于扩充。还有 NULL也是一个无意义的单词。34:当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。 说明:这样可以增加编程效率和程序的可读性。示例:在某过程中较多引用TheReceiveBufferFirstSocket.byDataPtr,则可以通过以下宏定义来代替:# define pSOCKDATA TheReceiveBufferFirstScoket.byDataPtr