C++编程规范.pdf

上传人:文*** 文档编号:88942260 上传时间:2023-05-04 格式:PDF 页数:61 大小:5.83MB
返回 下载 相关 举报
C++编程规范.pdf_第1页
第1页 / 共61页
C++编程规范.pdf_第2页
第2页 / 共61页
点击查看更多>>
资源描述

《C++编程规范.pdf》由会员分享,可在线阅读,更多相关《C++编程规范.pdf(61页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、C编程规范说明感谢为编程规范作出辛勤劳动的作者!本规范总则的内容包括:排版、注释、标识符命名、变量使用、代码可测性、程序效率、质量保证、代码编译、单元测试、程序版本与维护等。本规范总则的示例都以c语言为背景,采用以下的术语描述:规则:编程时强制必须遵守的原则。建议:编程时必须加以考虑的原则。说明:对此规则或建议进行必要的解释。示例:对此规则或建议从正、反两个方面给出例子。目 录1排版2注释3标识符命名4可读性5变量、结构6函数、过程7可测性8程序效率9质量保证1 0代码编辑、编译、审查1 1代码测试、维护1 2宏611182022283640445052531排版*1-1:程序块要采用缩进风格

2、编写,缩进的空格数为4个。说明:对于由开发工具自动生成的代码可以有不一致。*1-2:相对独立的程序块之间、变量说明之后必须加空行。示例:如下例子不符合规范。if(!valid_ni(ni)(./program coderepssn_ind=ssn_dataindex.repssn_index;repssn_ni=ssn_dataindex.ni;应如下书写if(!valid_ni(ni)(/program code)repssn_ind=ssn_dataindex.repssn_index;repssn_ni=ssn_dataindex.ni;*1-3:较长的语句(80字符)要分成多行书写,长

3、表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。示例:perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN+STAT_SIZE_PER_FRAM*sizeof(_UL);act_task_tableframe_id*STAT_TASK_CHECK_NUMBER+index.occupied=stat_poiindex.occupied;act_task_tabletaskno.duration_true_or_false=SYS_get_sccp_statistic_state(stat

4、_item);report_or_not_flag=(taskno MAX_ACT_TASK_NUMBER)&(n7stat_stat_item_valid(stat_item)&(act_task_tabletaskno.result_data!=0);口-4:循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。示例:if(taskno max_act_task_number)&(n7stat_stat_item_valid(stat_item)(/program code)for(i=0,j =0;(i BufferKey

5、wordword_index.word_length)&(j NewKeyword.word_length);i+,j+)(/program code)for(i=0,j =0;(i first_word_length)&(j for do while case、switch default等语句自占一行,且if、for do、while等语句的执行语句部分无论多少都要加括号 葭示例:如下例子不符合规范。if(pUserCR=NULL)return;应如下书写:if(pUserCR=NULL)(return;1-8:对齐只使用空格键,不使用TAB键。说明:以免用不同的编辑器阅读程序时,因TAB

6、键所设置的空格数目不同而造成程序布局不整齐,不要使用BC作为编辑器合版本,因为BC会自动将8个空格变为一个TAB键,因此使用BC合入的版本大多会将缩进变乱。*1-9:函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。1-10;程序块的分界符(如C/C+语 言 的 大 括 号 厂 和 ,)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for,do、while、switch、case语句中的程序都要采用如上的缩进方式。示例:如下例子不符合规范。for(.)./

7、program codeif(.)./program codevoid example_fun(void)/program code)应如下书写。for(.)(/program code)if()./program code)void example_fun(void)(./program code)1-1 1:在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如一),后不应加空格。说明:采用这种松散方式编写代码的目的是使代码更加清晰。由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留

8、空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C+语言中括号已经是最清晰的标志了。在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。示例:(1)逗号、分号只在后面加空格。int a,b,c;(2)比较操作符,赋值操作符=、算术操作符 +、3,逻辑操作符,&、位域操作符 =MAX_TIME_VALUE)a=b+c;a*=2;a=b A 2;(3)“!“、”(地址运算符)等单目操作符前后不加空格。*P=0;/内容操作*”与内容之间flag=!isEmpty;/非操作!”与

9、内容之间p=&mem;/地 址 操 作 与 内 容 之 间i+;/”+与内容之间(4)前后不加空格。p-id=pid;/指针前后不加空格(5)if for、while switch等与后面的括号间应加空格,使if等关键字更为突出、明显。if(a=b&c d)V21-1:一行程序以小于80字符为宜,不要写得过长。22注释2-1:一般情况下,源程序有效注释量必须在20%以上。说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。12-2:说明性文件(如头文件.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注

10、释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。示例:下面这段头文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。/*Copyright(C),1988-1999,Huawei Tech.Co.r Ltd.File name:/文件名Author:Version:Date:/作者、版本及完成日期Description:/用于详细说明此程序文件完成的主要功能,与其他模块/或函数的接口,输出值、取值范围、含义及参数间的控/制、顺序、独立或依赖等关系Others:/其它内容的说明Function Li

11、st:/主要函数列表,每条记录应包括函数名及功能简要说明1.History:/修改历史记录列表,每条修改记录应包括修改口期、修改/者及修改内容简述1.Date:Author:Modification:2.*2-3:源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。2/*Copyright(C)f 1988-1999,Huawei Tech.Co.,Ltd.FileName:test.cppAuthor:Version:Date:Description

12、:/模块描述Version:/版本信息Function List:/主要函数及其功能1.-History:/历史修改记录 David 96/10/12 1.0 build this moudle*/说明:Description 项描述本文件的内容、功能、内部各部分之间的关系及本文件与其它文件关系等。History是修改历史记录列表,每条修改记录应包括修改日期、修改者及修改内容简述。)2-4:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关 系(函数、表)等。示例:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。Function:/函数

13、名称Description:/函数功能、性能等的描述Calls:/被本函数调用的函数清单Called By:/调用本函数的函数清单Table Accessed:/被访问的表(此项仅对于牵扯到数据库操作的程序)Table Updated:/被修改的表(此项仅对于牵扯到数据库操作的程序)Input:/输入参数说明,包括每个参数的作/用、取值说明及参数间关系。Output:/对输出参数的说明。Return:/函数返回值的说明Others:/其它说明*2*2-5:边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。*2-6:注释的内容要清楚、明了,含义准确,防止

14、注释二义性。说明:错误的注释不但无益反而有害。规则2-7:避免在注释中使用缩写,特别是非常用缩写。说明:在使用缩写时或之前,应对缩写进行必要的说明。*2-8:注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。示例:如下例子不符合规范。例1:/*get replicate sub system index and net indicator*/repssn_ind=ssn_dataindex.repssn_index;repssn_ni=ssn_dataindex.ni;例2:repssn_ind=ssn_

15、dataindex.repssn_index;repssn_ni=ssn_dataindex.ni;/*get replicate sub system index and net indicator*/应如下书写/*get replicate sub system index and net indicator*/repssn_ind=ssn_dataindex.repssn_index;repssn_ni=ssn_dataindex.ni;12-9:对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或

16、右方。示例:/*active statistic task number*/#define MAX_ACT_TASK_NUMBER 10002#define MAX_ACT_TASK_NUMBER 1000/*active statistic task number*/12-10:数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。示例:可按如下形式说明枚举/数据/联合结构。/*seep interface with seep user primitive message

17、 name*/enum SCCP_USER_PRIMITIVE(N_UNITDATA_INDZ/*seep notify seep user unit data come*/N_NOT工CE_工ND,/*seep notify user the No.7 network can not*/*transmission this message*/N_UN工TDATA_REQ,/*seep user 1s unit data transmission request*/;*2-11:全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。示例:/*The

18、ErrorCode when SCCP translate*/*Global Title failure,as follows*/变量作用、含义/*0-SUCCESS 1 GT Table error*/*2 GT error Others no use*/变量取值范围/only function SCCPTranslate()in/*this modual can modify it,and other*/*module can visit it through call*/*the function GetGTTransErrorCode()*/使用方法BYTE g_GTTranError

19、Code;-12:注释与所描述内容进行同样的缩排。说明:可使程序排版整齐,并方便注释的阅读与理解。示例:如下例子,排版不整齐,阅读稍感不方便。void example_fun(void)(/*code one comments*/CodeBlock One2/*code two comments*/CodeBlock Two)应改为如下布局。void example_fun(void)(/*code one comments*/CodeBlock One/*code two comments*/CodeBlock Two)2-13:将注释与其上面的代码用空行隔开。示例:如下例子,显得代码过于紧

20、凑。/*code one comments*/program code one/*code two comments*/program code two应如下书写/*code one comments*/program code one/*code two comments*/program code two*2-14:对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。12-15:对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一

21、个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。说明:这样比较清楚程序编写者的意图,有效防止无故遗漏break语句。2示例(注意斜体加粗部分):case CMD_UP:ProcessUp();break;case CMD_DOWN:ProcessDown();break;case CMD_FWD:ProcessFwd();if(.)(break;)else(ProcessCFW_B();/now jump in to case CMD_A)case CMD_A:ProcessA();break;case CMD_B:ProcessB();break;case C

22、MD_C:ProcessC();break;case CMD_D:ProcessD();2break;/22-1:避免在一行代码或表达式的中间插入注释。说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。%22 通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。%2-3:在代码的功能、意图层次上进行注释,提供有用、额外的信息。说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。示例:如下注释意义不大。

23、/*if receive_flag is TRUE*/if(receive_flag)而如下的注释则给出了额外有用的信息。/*if mtp receive a message from links*/if(receive_flag)3:在程序块的结束行右方加注释标记,以表明某程序块的结束。说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。示例:参见如下例子。if(.)(/program codewhile(index MAX_INDEX)/program code /*end of while(index MAX_INDEX)*/指明该条while语句结束 /*end

24、of if(.)*/指明是哪条if语句结束力25:注释格式尽量统一,建议使用/*/2V22-6:注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。3 标志符命名3标识符命名*3-1:标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。示例:如下单词的缩写能够被大家基本认可。temp可 缩 写 为

25、tmp;flag可 缩 写 为fig;statistic 可缩写为 stat;increment 可缩写为 inc;message可缩写为 msg;1 3-2:命名中若使用特殊约定或缩写,则要有注释说明。说明:应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。3-3:自己特有的命名风格,要自始至终保持一致,不可来回变化。说明:个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。13-4:对于变量命名,禁止取单个字符(如i、j、k.),建议除了要有具体含义外,还能表明其变量类型、数据类型

26、等,但i、j、k作局部循环变量是允许的。说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。示例:下面所示的局部变量名的定义方法可以借鉴。int liv_Width其变量名解释如下:1 局 部 变 量(Local)(其它:g 全 局 变 量(Global).)i 数 据 类 型(Interger)v 变 量(Variable)(其它:c 常 量(Const).)W i d t h变量含义3标志符命名这样可以防止局部变量与全局变量重名。*3-5:命名规范必须与所使用的系统风格保持一致,并在同一项目中统一,比

27、如采用UNIX的全小写加下划线的风格或大小写混排的方式,不要使用大小写与下划线混排的方式,用作特殊标识如标识成员变量或全局变量的m_和g_,其后加上大小写混排的方式是允许的。示例:Add_User不允许,add_user、AddUser、m_AddUser允许。e:除非必要,不要用数字或较奇怪的字符来定义标识符。示例:如下命名,使人产生疑惑。#define _EXAMPLE_O_TEST_#define _EXAMPLE_1_TEST_void set_sls00(BYTE sis);应改为有意义的单词命名#define _EXAMPLE_UNIT_TEST_#define _EXAMPLE_

28、ASSERT_TEST_void set_udt_msg_s 1 s(BYTE sis);%32 在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。说明:对接口部分的标识符应该有更严格限制,防止冲突。如可规定接口部分的变量与常量之前加上“模块”标识等。%33:用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。说明:下面是些在软件中常用的反义词组。add/remove begin/endinsert/delete first/lastincrement/decrementadd/deletemin/maxnext/previoussend

29、/receivecut/paste示例:int min_sum;lock/unlockold/newsource/targetsource/destinationup/downcreate/destroyget/releaseput/getopen/closestart/stopshow/hide3 标志符命名int max_sum;int add_user(BYTE*user_name);int delete_user(BYTE*user_name);V23-4:除了编译开关/头文件等特殊应用,应避免使用_ E 3 P L E _ T E S T _之类以下划线开始和结尾的定义。4 可读性4

30、可读性4-1:注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。说明:防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。示例:下列语句中的表达式word=(high 8)|low(1)if(a|b)&(a&c)if(a|b)(c&d)如果书写为high 8a I b&a&ca|b c&dhigh 8|low=(highI low,a|b&a&c=(a I b)&c),(1)(2)不会出错,但语句不易理解;a|b c&d=a|(b 6-2:明确函数功能,精确(而不是近似)地实现函数设计。6-3:编写可重入函数时,应注意局部变量的使用(如编写C/C+语言的

31、可重入函数时,应使用aut。即缺省态局部变量或寄存器变量)。说明:编写C/C+语言的可重入函数时,不应使用s ta t ic 局部变量,否则必须经过特殊处理,才能使函数具有可重入性。16-4:编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。示例:假设Exam是i n t 型全局变量,函数Squre_Exam返回Exam平方值。那么如下函数不具有可重入性。unsigned in t exam ple(in t p ara)(u

32、nsigned in t temp;Exam=para;/(*)temp=Square_Exam();re tu rn temp;此函数若被多个进程调用的话,其结果可能是未知的,因为当(*)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使Exam赋与另一个不同的p ara值,所以当控制重新回到temp=Square_Exam()ff后,计算出的temp很可能不是预想中的结果。此函数应如下改进。unsigned in t exam ple(in t p ara)unsigned in t temp;6函数、过程 申请信号量操作】/若申请不到“信号量”

33、,说明另外的进程正处于Exam=para;/给Exam赋值并计算其平方过程中(即正在使用此temp=Square_Exam();/信 号),本进程必须等待其释放信号后,才可继 释放信号量操作 /续执行。若申请到信号,则可继续执行,但其/它进程必须等待本进程释放信号量后,才能再使/用本信号。return temp;16-5:在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接函数本身负责,缺省是由函数调用者负责。说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这必要的处理过程,

34、造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。/26-1:防止将函数的参数作为工作变量。说明:将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。示例:下函数的实现不太好。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成了工作变量,不太

35、好。)若改为如下,则更好些。void sum_data(unsigned int num,int*data,int*sum)6 函数、过程unsigned int count;int sum_temp;sum_temp=0;for(count=0;count b)?a:b;改为如下就很清晰了。int max(int a,int b)(return(a b)?a:b);)value=max(a,b);或改为如下。#define MAX(a,b)(a)(b)?(a):(b)value=MAX(a,b);6函数、过程/26-5:不要设计多用途面面俱到的函数。说明:多功能集于一身的函数,很可能使函数的

36、理解、测试、维护等变得困难。V26-6:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出。说明:带有内部“存储器”的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在C/C+语言中,函数的static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是STATIC的局部变量的地址作为返回值,若为AUT。类,则返回为错针。示例:如下函数,其返回值(即功能)是不可预测的。unsigned int integer_sum(unsigned int base)(

37、unsigned int index;static unsigned int sum=0;/注意,是static类型的。/若改为aut。类型,则函数即变为可预测。for(index=1;index B-C-A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。V26-25:仔细分析模块的功能及性能需求,并进一步细分,同时若有必要画出有关数据流图,据此来进行模块的函数划分与组织。说明:函数的划分与组织是模块的实现过程中很关键的步骤,如何划分出合理的函数结构,关系到模块的最终效率和可维护性、

38、可测性等。根据模块的功能图或/及数据流图映射出6 函数、过程函数结构是常用方法之一。/26-26:改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性。优化函数结构时,要遵守以下原则:(1)不能影响模块功能的实现。(2)仔细考查模块或函数出错处理及模块的性能要求并进行完善。(3)通过分解或合并函数来改进软件结构。(4)考查函数的规模,过大的要进行分解。(5)降低函数间接口的复杂度。(6)不同层次的函数调用要有较合理的扇入、扇出。(7)函数功能应可预测。(8)提高函数内聚。(单一功能的函数内聚最高)说明:对初步划分后的函数结构应进行改进、优化,使之更为合理。

39、V26-27:在多任务操作系统的环境下编程,要注意函数可重入性的构造。说明:可重入性是指函数可以被多个任务进程调用。在多任务操作系统中,函数是否具有可重入性是非常重要的,因为这是多个进程可以共用此函数的必要条件。另外,编译器是否提供可重入函数库,与它所服务的操作系统有关,只有操作系统是多任务时,编译器才有可能提供可重入函数库。如DOS下BC和MSC等就不具备可重入函数库,因为DOS是单用户单任务操作系统。%6-28:避免使用BOOL参数。说明:原因有二,其一是BOOL参数值无意义,TURE/FALSE的含义是非常模糊的,在调用时很难知道该参数到底传达的是什么意思;其二是BOOL参数值不利于扩充

40、。还有NULL也是一个无意义的单词。/26-29:对于提供了返回值的函数,在引用时最好使用其返回值。力6-30:当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。说明:这样可以增加编程效率和程序的可读性。示例:在某过程中较多引用TheReceiveBuf fer FirstSocket.byDataPtr,则可以通过以下宏定义来代替:#define pSOCKDATA TheReceiveBufferFirstScoket.byDataPtr7可测性7可测性*7-1:在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数

41、,并且要有详细的说明。说明:本规则是针对项目组或产品组的。*7-2:在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号。说明:统一的调测信息格式便于集成测试。7-3:编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明。测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关)。说明:为单元测试而准备。7-4:在进行集成测试/系统联调之前,要构造好测试环境、测试项目及测试用例,同时仔细分析并优化测试用例,以提高测试效率。说明:好的测试用例应尽可能模拟出程序所遇到

42、的边界值、各种复杂环境及一些极端情况等。*7-5:使用断言来发现软件问题,提高代码可测性。说明:断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否则应报告),它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐臧很深,用其它手段极难发现的问题进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。示例:下面是C语言中的一个断言,用宏来设计的。(其中NULL为0L)#ifdef _EXAM_ASSERT_TEST_/若使用断言测试void exam_assert(char*file_namez unsigned int

43、line_no)(printf(nnEXAMAssert failed:%s,line%unH,file_nameA line_no);abort();7可测性)#define EXAM_ASSERT(condition)if(condition)/若条件成立,则无动作NULL;else/否则报告exam_assert(_FILE_,_LINE_)#else/若不使用断言测试#define EXAM_ASSERT(condition)NULL#endif/*end of ASSERT*/*7-6:用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况。*7-7:不能用断言来检查最终产

44、品肯定会出现且必须处理的错误情况。说明:断言是用来处理不应该发生的错误情况的,对于可能会发生的且必须处理的情况要写防错程序,而不是断言。如某模块收到其它模块或链路上的消息后,要对消息的合理性进行检查,此过程为正常的错误检查,不能用断言来实现。*7-8:对较复杂的断言加上明确的注释。说明:为复杂的断言加注释,可澄清断言含义并减少不必要的误用。*7-9:用断言确认函数的参数。示例:假设某函数参数中有一个指针,那么使用指针前可对它检查,如下。int exam_fun(unsigned char*str)(EXAM_ASSERT(str!=NULL);/用断言检查“假设指针不为空”这个条件/other

45、 program code)17-10:用断言保证没有定义的特性或功能不被使用。示例:假设某通信模块在设计时,准备提供“无连接”和“连接”这两种业务。但当前7可测性的版本中仅实现了“无连接”业务,且在此版本的正式发行版中,用户(上层模块)不应产 生“连接”业务的请求,那么在测试时可用断言检查用户是否使用“连接”业务。如下。#define EXAM_CONNECTIONLESS 0/无连接业务#define EXAM_CONNECTION 1 /连接业务int msg_process(EXAM_MESSAGE*msg)(unsigned char service;/*message servic

46、e class/EXAM_ASSERT(msg!=NULL);service=get_msg_service_class(msg);EXAM_ASSERT(service!=EXAM_CONNECT工ON);/假设不使用连接业务./other program code)17-11:用断言对程序开发环境(OS/Compiler/Hardware)的假设进行检查。说明:程序运行时所需的软硬件环境及配置要求,不能用断言来检查,而必须由一段专门代码处理。用断言仅可对程序开发环境中的假设及所配置的某版本软硬件是否具有某种功能的假设进行检查。如某网卡是否在系统运行环境中配置了,应由程序中正式代码来检查;而

47、此网卡是否具有某设想的功能,则可由断言来检查。对编译器提供的功能及特性假设可用断言检查,原因是软件最终产品(即运行代码或机器码)与编译器已没有任何直接关系,即软件运行过程中(注意不是编译过程中)不会也不应该对编译器的功能提出任何需求。示例:用断言检查编译器的int型数据占用的内存空间是否为2,如下。EXAM_ASSERT(sizeof(int)=2);*7-12:正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关 掉)。说明:加快软件运行速度。7-13:在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响。说明:即有测试代码的软件和关掉测试代码的软件,在功能行为上应一

48、致。7 可测性17-14:用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度。7-15:软件的DEBUG版本和发行版本应该统一维护,不允许分家,并且要时刻注意保证两个版本在实现功能上的一致性。/27-1:在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等。说明:程序的调试与测试是软件生存周期中很重要的一个阶段,如何对软件进行较全面、高率的测试并尽可能地找出软件中的错误就成为很关键的问题。因此在编写源代码之前,除了要有一套比较完善的测试计划外,还应设计出一系列代码测试手段,为单元测试

49、、集成测试及系统联调提供方便。%7 2调测开关应分为不同级别和类型。说明:调测开关的设置及分类应从以下几方面考虑:针对模块或系统某部分代码的调测;针对模块或系统某功能的调测;出于某种其它目的,如对性能、容量等的测试。这样做便于软件功能的调测,并且便于模块的单元测试、系统联调等。%7-3:编写防错程序,然后在处理错误之后可用断言宣布发生错误。示例:假如某模块收到通信链路上的消息,则应对消息的合法性进行检查,若消息类别不是通信协议中规定的,则应进行出错处理,之后可用断言报告,如下例。#ifdef _EXAM_ASSERT_TEST_/若使用断言测试/*Notice:this function do

50、es not call fabort1 to exit program*/void assert_report(char*file_namez unsigned int line_no)(printf(nEXAMError Report:%s,line%un”,file_namer line_no);)#define ASSERT_REPORT(condition)if(condition)/若条件成立,则无动作NULL;else/否则报告7 可测性assert_report(FILE,LINE)#else/若不使用断言测试#define ASSERT_REPORT(condition)NUL

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁