华为软件编码规范(6)

2019-04-15 16:28

?8-2:仔细考查、分析系统及模块处理输入(如事务、消息等)的方式,并加以改进

?8-3:对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率 说明:软件系统的效率主要与算法、处理任务方式、系统功能及函数结构有很大关系,仅在代码上下功夫一般不能解决根本问题。

?8-4:编程时,要随时留心代码效率;优化代码时,要考虑周全 ?8-5:不应花过多的时间拼命地提高调用不很频繁的函数代码效率 说明:对代码优化可提高效率,但若考虑不周很有可能引起严重后果。 ?8-6:要仔细地构造或直接用汇编编写调用频繁或性能要求极高的函数

说明:只有对编译系统产生机器码的方式以及硬件系统较为熟悉时,才可使用汇编嵌入方式。嵌入汇编可提高时间及空间效率,但也存在一定风险。

?8-7:在保证程序质量的前提下,通过压缩代码量、去掉不必要代码以及减少不必要的局部和全局变量,来提高空间效率

说明:这种方式对提高空间效率可起到一定作用,但往往不能解决根本问题。 ?8-8:在多重循环中,应将最忙的循环放在最内层 说明:减少CPU切入循环层的次数。 示例:如下代码效率不高。

for (row = 0; row < 100; row++) {

for (col = 0; col < 5; col++) {

sum += a[row][col]; } }

可以改为如下方式,以提高效率。 for (col = 0; col < 5; col++) {

for (row = 0; row < 100; row++) {

sum += a[row][col]; } }

?8-9:尽量减少循环嵌套层次

?8-10:避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中

说明:目的是减少判断次数。循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。 示例:如下代码效率稍低。

for (ind = 0; ind < MAX_RECT_NUMBER; ind++) {

if (data_type == RECT_AREA) {

area_sum += rect_area[ind]; } else

{

rect_length_sum += rect[ind].length; rect_width_sum += rect[ind].width; } }

因为判断语句与循环变量无关,故可如下改进,以减少判断次数。 if (data_type == RECT_AREA) {

for (ind = 0; ind < MAX_RECT_NUMBER; ind++) {

area_sum += rect_area[ind]; } } else {

for (ind = 0; ind < MAX_RECT_NUMBER; ind++) {

rect_length_sum += rect[ind].length; rect_width_sum += rect[ind].width; } }

?8-11:尽量用乘法或其它方法代替除法,特别是浮点运算中的除法 说明:浮点运算除法要占用较多CPU资源。 示例:如下表达式运算可能要占较多CPU资源。 #define PAI 3.1416

radius = circle_length / (2 * PAI); 应如下把浮点除法改为浮点乘法。

#define PAI_RECIPROCAL (1 / 3.1416 ) // 编译器编译时,将生成具体浮点数 radius = circle_length * PAI_RECIPROCAL / 2; ?8-12:不要一味追求紧凑的代码

说明:因为紧凑的代码并不代表高效的机器码。

〔九〕 =====[ 质量保证 ]=====

19-1:在软件设计过程中构筑软件质量 19-2:代码质量保证优先原则

(1)正确性,指程序要实现设计要求的功能。 (2)稳定性、安全性,指程序稳定、可靠、安全。 (3)可测试性,指程序要具有良好的可测试性。

(4)规范/可读性,指程序书写风格、命名规则等要符合规范。 (5)全局效率,指软件系统的整体效率。

(6)局部效率,指某个模块/子模块/函数的本身效率。 (7)个人表达方式/个人方便性,指个人编程习惯。 19-3:只引用属于自己的存贮空间

说明:若模块封装的较好,那么一般不会发生非法引用他人的空间。

19-4:防止引用已经释放的内存空间

说明:在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块(如C语言指针),而另一模块在随后的某个时刻又使用了它。要防止这种情况发生。 19-5:过程/函数中分配的内存,在过程/函数退出之前要释放

19-6:过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭

说明:分配的内存不释放以及文件句柄不关闭,是较常见的错误,而且稍不注意就有可能发生。这类错误往往会引起很严重后果,且难以定位。

示例:下函数在退出之前,没有把分配的内存释放。 typedef unsigned char BYTE;

int example_fun( BYTE gt_len, BYTE *gt_code ) {

BYTE *gt_buf;

gt_buf = (BYTE *) malloc (MAX_GT_LENGTH);

... //program code, include check gt_buf if or not NULL. /* global title length error */ if (gt_len > MAX_GT_LENGTH) {

return GT_LENGTH_ERROR; // 忘了释放gt_buf }

... // other program code }

应改为如下。

int example_fun( BYTE gt_len, BYTE *gt_code ) {

BYTE *gt_buf;

gt_buf = (BYTE * ) malloc ( MAX_GT_LENGTH ); ... // program code, include check gt_buf if or not NULL. /* global title length error */ if (gt_len > MAX_GT_LENGTH) {

free( gt_buf ); // 退出之前释放gt_buf return GT_LENGTH_ERROR; }

... // other program code }

19-7:防止内存操作越界

说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。

示例:假设某软件系统最多可由10个用户同时使用,用户号为1-10,那么如下程序存在问题。 #define MAX_USR_NUM 10

unsigned char usr_login_flg[MAX_USR_NUM]= \ void set_usr_login_flg( unsigned char usr_no ) {

if (!usr_login_flg[usr_no])

{

usr_login_flg[usr_no]= TRUE; } }

当usr_no为10时,将使用usr_login_flg越界。可采用如下方式解决。 void set_usr_login_flg( unsigned char usr_no ) {

if (!usr_login_flg[usr_no - 1]) {

usr_login_flg[usr_no - 1]= TRUE; } }

19-8:认真处理程序所能遇到的各种出错情况

19-9:系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用 19-10:系统运行之初,要对加载到系统中的数据进行一致性检查 说明:使用不一致的数据,容易使系统进入混乱状态和不可知状态。 19-11:严禁随意更改其它模块或系统的有关设置和配置

说明:编程时,不能随心所欲地更改不属于自己模块的有关设置如常量、数组的大小等。 19-12:不能随意改变与其它模块的接口

19-13:充分了解系统的接口之后,再使用系统提供的功能

示例:在B型机的各模块与操作系统的接口函数中,有一个要由各模块负责编写的初始化过程,此过程在软件系统加载完成后,由操作系统发送的初始化消息来调度。因此就涉及到初始化消息的类型与消息发送的顺序问题,特别是消息顺序,若没搞清楚就开始编程,很容易引起严重后果。以下示例引自B型曾出现过的实际代码,其中使用了FID_FETCH_DATA与FID_INITIAL初始化消息类型,注意B型机的系统是在FID_FETCH_DATA之前发送FID_INITIAL的。 MID alarm_module_list[MAX_ALARM_MID];

int FAR SYS_ALARM_proc( FID function_id, int handle ) {

_UI i, j;

switch ( function_id ) {

... // program code case FID_INITAIL:

for (i = 0; i < MAX_ALARM_MID; i++) {

if (alarm_module_list[i]== BAM_MODULE // **) || (alarm_module_list[i]== LOCAL_MODULE) {

for (j = 0; j < ALARM_CLASS_SUM; j++) {

FAR_MALLOC( ... ); } } }

... // program code break;

case FID_FETCH_DATA: ... // program code

Get_Alarm_Module( ); // 初始化alarm_module_list break;

... // program code } }

由于FID_INITIAL是在FID_FETCH_DATA之前执行的,而初始化alarm_module_list是在FID_FETCH_DATA中进行的,故在FID_INITIAL中(**)处引用alarm_module_list变量时,它还没有被初始化。这是个严重错误。

应如下改正:要么把Get_Alarm_Module函数放在FID_INITIAL中(**)之前;要么就必须考虑(**)处的判断语句是否可以用(不使用alarm_module_list变量的)其它方式替代,或者是否可以取消此判断语句。

19-14:编程时,要防止差1错误

说明:此类错误一般是由于把“<=”误写成“<”或“>=”误写成“>”等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心。当编完程序后,应对这些操作符进行彻底检查。 19-15:要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误 说明:形式相近的操作符最容易引起误用,如C/C++中的“=”与“==”、“|”与“||”、“&”与“&&”等,若拼写错了,编译器不一定能够检查出来。 示例:如把“&”写成“&&”,或反之。

ret_flg = (pmsg->ret_flg & RETURN_MASK); 被写为:

ret_flg = (pmsg->ret_flg && RETURN_MASK);

rpt_flg = (VALID_TASK_NO( taskno ) && DATA_NOT_ZERO( stat_data )); 被写为:

rpt_flg = (VALID_TASK_NO( taskno ) & DATA_NOT_ZERO( stat_data ));

19-16:有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支

19-17:Unix下,多线程的中的子线程退出必需采用主动退出方式,即子线程应return出口。

19-18:不要滥用goto语句。

说明:goto语句会破坏程序的结构性,所以除非确实需要,最好不使用goto语句。

?9-1:不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性

?9-2:除非为了满足特殊需求,避免使用嵌入式汇编 说明:程序中嵌入式汇编,一般都对可移植性有较大的影响。

?9-3:精心地构造、划分子模块,并按“接口”部分及“内核”部分合理地组织子模块,以提高“内核”部分的可移植性和可重用性

说明:对不同产品中的某个功能相同的模块,若能做到其内核部分完全或基本一致,那么无论对产品的测试、维护,还是对以后产品的升级都会有很大帮助。 ?9-4:精心构造算法,并对其性能、效率进行测试 ?9-5:对较关键的算法最好使用其它算法来确认


华为软件编码规范(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:5学原理》(宏观)第五版测试题库 (25)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: