C语言编程规范_第1页
C语言编程规范_第2页
C语言编程规范_第3页
C语言编程规范_第4页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

软件标准化.前言背景适用人员公司的所有PC软件编写和ARM嵌入式软件以及单片机软件编写人员。2.编程规范编程规范的主要部分,本章将向您介绍排版、注释、命名等诸多的内容。为了能够说明问题,本文中的每一条规范几乎都采用了说明加示例的方式,见下表。重要性★★★说明•目的难易度修改难度/对于不同的编辑器门动牛.成物代俞ス以仃不应使用空格而非TAB键。voidmain()return0;校对方法参考资料备注信息目视说明•目的详细说明此条规范的作用以及ー些注意事项。程序示例利用“正确示例”和“错误示例”来进ー步说明规范应掌握的内容。正确示例将会用绿色字体注明正确的方式。错误示例会用红色字体注明错误的方式。校对方法说明对此规范进行审核的方法。一般为目视法。重要性说明此规范的亜要程度。三颗星代表最重要,ー颗星代表一般。难易度说明掌握此规范的难易程度。三颗星代表很难掌握,ー颗星代表很易掌握。修改难度表示如果在编程时没有按照此规范进行书写,会给程序的修改带来多大的难度。三颗星代表很难修改,ー颗星代表很易修改。2.1格式第1条:程序块要采用缩进风格编写,缩进的空格数为4个。重要性难易度修改难度★★★★★说明•目的对于不同的编辑器自动生成的代码可以有不一致的现象,因此在进行缩进时,应使用空格而非TAB键。正确示例错误示例voidmain()(return0;/Z缩进4个空格,iE确。)voidmain()(inti=0;//没有缩进,错误!return0;/Z缩进2个空格,错误!)校对方法目视参考资料备注信息第2条:相对独立的程序块之间、变量说明之后必须加空行。重要性难易度修改难度★★★★说明•目的为了使程序块与变量、程序块与程序块之间能够有比较明显的分割,提高程序的层次感,需要在相对独立的程序块之间、变量说明之后加空行。正确示例错误示例voidmain()inti;floatf;/Z空行,正确。f=(float)i*2.0;/Z空行,正确。return0;)voidmain()(inti;floatf; //未空行,错误!f=(float)i*2.0;//未空行,错误!return0;)校对方法目视参考资料备注信息

第3条:书写较长的语句(大于80字符)、循环判断等语句、函数参数时,要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。重要性难易度修改难度★★★★说明•目的为了使代码能够显示在整个屏幕中,避免单行代码过长,增加程序的可读性,在编写单行大于80个字符的语句时,应分多行书写。如果是带有多个操作符的长表达式,操作符应放在新行之首。划分出的新行要有适当的缩进,一般应与首行对齐,使排版整齐,语句可读。正确示例错误示例//累加运算my_time=systime.hour+sectime.min+systime.sec;/Z赋值语句my_signal=signail&&signal2&&signal3&&signal4&&signals&&signal6&&signal7;//条件判断if((taskno<max_act_task_number)&&(stat-valid(stat_item))){//...程序代码)/Z循环语句for(i=0,j=0;(i<old_kw.word_length)&&(j<new_kw.word_length);i++,j++){//...程序代码)/Z函数调用str_compare((BYTE*)&stat_object,(BYTE*)&(tasks[taskno].object),sizeof(_STAT_OBJECT));/Z多行书写,且缩进整齐,正确。//累加运算my_time=systime.hour+systime.min+syst/Z赋值语句my—signal=signall&&signal2&&signal3//条件判断if((taskno<max_act_task_number)&&(s(//.•・程序代码)//循环语句for(i=0,j=0;(i<old_kw.word_length)&&(//••,程序代码}/Z函数调用str_compare((BYTE*)&stat_objectr(BYTE*)&(/Z单行书写,导致部分代码无法看到,错误!校对方法目视参考资料备注信息

第4条:不允许把多个短语句写在一行中,即一行只写一条语句。重要性难易度修改难度★★★★说明•目的不允许将多个短语句写在一行中,虽然这样看上去可以节省版面,但却加大了程序的读写难度,破坏了程序的整体结构。正确示例错误示例rect.left=0;rect.top=0;rect.left=0;rect.top=0;//单行书写,错误!校对方法目视参考资料备注信息第5条:if-,for、do、while、case、switch-,default等语句自占一行,且if、for-,do、while等语句的执行语句部分无论多少都要加括号{}〇重要性难易度修改难度★★★★说明・目的为了增加程序的层次感,if、for>do、while>case>switchdefault等语句自占一行,且if、for>do、while等语句的执行语句部分无论多少都要加括号{レ “{”需要另起一行,并写在行首。正确示例错误示例if(pUser==NULL){return;)if((pMotorl==NULL)&&(pMotor2==NULL)&&(pMotor3==NULL)){return;if(pUser==NULL)return;//没有书写(},错误!if((pMotorl==NULL)&&(pMotor2==NULL)&&(pMotor3==NULL)){return;)//“ビ没有另起一行,错误!校对方法目视参考资料备注信息

第6条:在case语句中尽量不要申请临时变量,否则在case下需要使用{レ并相对case缩进4个空格。break应相对case缩进4个空格。defaulセ语句下如果没有程序块,则可以与break同写于一行,且“:”与break之间应有一个空格。否则与case语句使用同样的书写方法。如果case下的语句块最终需要return,则不需要break。说明•目的一般情况下,case语句中不应该申请临时变量,但对于ー些特殊的情况需要使用临时变量时,需要将case语句下的代码块用{)扩起来,代码块相对于{}应缩进4个空格,{}相对于case语句应缩进4个空格。正确示例错误示例switch(keyword){case0:(staticinti=0;if(i!=0){taskno=i;}else{i=0;taskno=0;})break;if(taskno==0)(return;)break;taskno=0;return;default:break;)switch(keyword){case0:staticinti=0;//没有使用{}/Z错误!if(i!=0){taskno=i;}else{i=0;taskno=0;}break;if(taskno==0){return;}break;:taskno=0;return;break;/Z此语句为无用语句。default:break;/Z应与default同写一行。错误!)校对方法目视参考资料备注信息重要性★★修改难度★★难易度★

第7条:在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符,后不应加空格。重要性难易度修改难度★★★★说明•目的采用这种松散方式编写代码的目的是使代码更加淸晰。由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C++语言中括号已经是最清晰的标志了。在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。正确示例错误示例//(1)逗号、分号只在后面加空格。inta,b,c;//(2)比较操作符,赋值操作符〃=“、算术//操作符"”、"%",逻辑操作符"&&"、"&",位域//操作符wくぐ、"”等双目操作符的前后加空格。if(current_time>=MAX_TIME_VALUE){a*=2;a=bA2;)//(3) n~","+ (地址运算符)/Z等单目操作符前后不加空格。*P='a'; //内容操作"*"与内容之间flag=lisEmpty;//非操作"!"与内容之间p=&mem; /Z地址操作"&"与内容之间i++; //"++ "与内容之间//(4)前后不加空格。p->id=pid; //"->"指针前后不加空格//(5)if、for«whilesswitch等与后面的括号/Z间应加空格,使if等关键字更为突出、明显。if(a>=b&&c>d)inta,b,c;//逗号后无空格,错误!if(current_time>=MAX_TIME__VALUE){a*=2;〃赋值、比较运算符前后无空格,错误!a=b人2;/Z赋值、比较运算符前后无空格,错误!}*p=1a1; //“★”后有空格,错误!flag=!isEmpty;//"!“后有空格,错误!p=&mem; // 后有空格,错误!i++; //“++”バー”前后有空格,错误!P->id=pid;//“ー〉”指针前后仃空格,错误!if(a>=b&&c>d)//if后无空格,错误!校对方法目视参考资料备注信息

2.2注释第8条:说明性文件和源程序文件(如.h文件、.c/.cpp文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。重要性难易度修改难度★★★★★说明•目的此规范要求注释清晰、详细。正确示例/★★★★★★★★★★★★★★★オ★★★★★★★★★★★★★★★★オ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★版权所有(C),1988-1999,普析通用公司.文件名: main.cpp原作者: 何乃文版本: vl.O日期:2004-10-1//此文件的创建日期说明: /Z用于详细说明此程序文件完成的主要功能,与其他模块或函数的接/Zロ,输出值、取值范围、含义及参数间的控制、顺序、独立或依赖等关系。其他:/Z其它内容的说明函数表: /Z主要函数列表,毎条记录应包括函数名及功能简要说明。GetRemoteDataSetRemoteData修改史: /Z修改历史记录列表,每条修改记录应包括修改H期、修改者及修改内容简述。1,日期://此次修改的日期作者:/Z此次修改的相关人员修改:/Z此次修改的修改内容2.日期:作者:修改:校对方法 r目视参考量料 备注信息

第9条:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。重要性难易度修改难度★★★★★说明•目的此规范要求注释清晰、详细。正确示例★★★★★★才オ★★★★★★★★オ★オ★★★オオオ★★★★★ホ★オ★★★★★★オ«★★★★★★★★★★★★★★オ米★★★オカオ★★★★★★ホオオ★★★函数名:/Z函数名称描述:/Z函数功能、性能等的描述调用函数:/Z被本函数调用的函数清单被调用函数:/Z调用本函数的函数清单被访问的表:/Z被访问的&(此项仅对于牵扯到数据库操作的程序)被修改的表://被修改的表(此项仅对于牵扯到数据库操作的程序)输A参数:/Z输入参数说明,包括每个参数的作用、取值说明及参数间关系。输出参数:/Z对输出参数的说明。返回值:/Z函数返回值的说明其他说明:/Z其它说明★★★,•★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★校对方法 目视参考资料备注信息

第10条: 注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。重要性难易度修改难度★★★说明・目的正确示例错误示例/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].index;repssn_ni=ssn_data[index].ni;//注释放在代码的上方且不隔行,正确。/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].index;repssn_ni=ssn_data[index].ni;repssn_ind=ssn_data[index].index;repssn_ni=ssn_data[index].ni;/*getreplicatesubsystemindexandnetindicator*//Z注释不应该与代码隔行或在代码的下方,错误!校对方法目视参考资料备注信息

第11条: 对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。重要性难易度修改难度★★★★说明•目的这些语句往往是程序实现某ー特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。正确示例错误示例inti=0; /Z函数返回值switch(key_word){/Z判断关键字的类型case0: /Z执行常规操作i=l;break;case1: //终止操作i=0;break;case2: //忽略错误i=-1;break;default:return0;/Z默认返回)returni;//程序和变量都有注释,正确。inti=0;switch(key_word){case0:i=1;break;=0;break;=-1;break;default:return0;}returni;//程序和变量没有注释,错误。校对方法目视参考资料备注信息

第12条: 对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下ー个case处理,必须在该case语句处理完、下ー个case语句前加上明确的注释。重要性「难易度「修改难度★★★★说明・目的这样比较清楚程序编写者的意图,有效防止无故遗漏break语句。正确示例错误示例caseCMD_UP:caseCMD_UP:ProcessUp();ProcessUp();break;break;caseCMD_DOWN:caseCMD_DOWN:ProcessDown();ProcessDown();if(・・・){if(...){break;break;}}else{else{ProcessCFW_B();//从这里協K至(JCMD_AProcessCFW_B();}}caseCMD_A:caseCMD_A:ProcessA();ProcessA();break;break;/Z对丁,连续执行的case的语句有注释,正确。/Z对于连续执行的case的语句无注释,错误。校对方法目视参考资料备注信息

2.3标志符命名第13条: 标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。命名中若使用特殊约定或缩写,则要有注释说明。重要性 难易度 修改难度★★★★★★说明•目的较短的単词可通过去掉“元音”形成缩写:较长的单词可取单词的头几个字母形成缩写:ー些单词有大家公认的缩写。最好是在名词面前还加上类型的第一个字母对于特殊的缩写喝约定,应该在源文件的开始之处,进行必要的注释说明。正确示例错误示例intiTmp; // tempintiMsg; // messagechariDir[100]; // directorylongiCmd; // command/オ★★★★オオ★★★★★★★★オホ★★★★★★★★オ・缩写说明:AD:模拟信号转换为数字信号Dark:暗电流BL:基线intGetAD〇;voidDarkCorrection();voidBeginBL();/Z使用公认且直观的缩写,正确。//对AD,等进行了说明inttp; // tempintmg; // messagechardy[100];// directorylongcm; // command//使用不公认且不直观的缩写,错误。intGetAD();voidDarkCorrection();voidBeginBL();/Z没有对缩写进行说明,错误。校对方法目视参考资料备注信息

第14条: 对于变量命名,禁止取单个字符(如i、j、k..建议除了要有具体含义外,还能表明其变量类型、数据类型等,但,j、k作局部循环变量是允许的。重要性难易度修改难度★★★★★★说明・目的变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。命名格式:〈范围前缀>_<数据类型><变量名称〉范围前缀: v,,局部变量(Variable) g_全局变量(Global)mー 类/结构成员变量(Member) c_ 常量(Const)数据类型: i 整型(Integer) ui 无符号整型(UnsignedInt)! 长整型(Long) u! 无符号长整型(UnsignedLong)r 实型(FloatDouble) a 字符型(Character)s 字符串型(String) b 布尔型(Boolean)〇 对象(ClassStruct) p 指针(可与其他类型混合使用)变量名称:变量名称应为首字符大写,且应以英文单词或词组命名。正确示例intg_iCurrentTaskIndex; //整数全局变量constintg_cMaxTaskNumber=100; //常数全局变量floatv_rData; /Z浮点数局部变量unsignedlong★g_ulpAddress; /Z无符号指针长整型全局变量classExampleclass{private:charm_aMsg[100]; /Z字符型类成员变量public:stringm_sErrorMsg[200]; //字符串型类成员变量boolm_bStatus; /Z布尔型类成员变量);Exampleclassv_oMessage; //对象类型局部变量校对方法目视参考资料备注信息

第15条: 命名规范必须与所使用的系统风格保持一致,并在同一项目中统ー。重要性难易度修改难度★★★★★说明•目的变量命名应符合变量命名规则,函数、类的命名应使用英文单词或词组顺序排列,且单词的首个字符应大写。除非必要,不要用数字或较奇怪的字符来定义标识符。宏定义应采取单词+下划线的方式命名,且全部大写。正确示例错误示例♦defineMAX_USER100voidAddUser();intGetCurrentUserIndex();classExampleclass(};/Z采用英文单词命名,且単词首个字符大写,/Z常量定义全部大写,正确。♦defineMAX_USER 100voidadd_Usr();intgetCurUserindex();classExample_Class();/Z采用英文单词命名,但单词首个字符小写,/Z且函数和类定义存在下划线,错误!校对方法目视参考资料备注信息第16条: 除了编译开关/头文件等特殊应用,应避免使用以下划线开始和结尾的定义。重要性难易度修改难度★★★★★说明•目的定义中可以使用下划线,但开始和结尾不应使用下划线。正确示例错误示例♦defineMAX_USER100♦defineDEBUG/Z下划线只出现咱定义中,正确。♦define_MAX_USER_100♦define_DEBUG_//定义前后出现下划线,错误!校对方法目视参考资料备注信息可读性第1フ条: 注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。重要性难易度修改难度★★★★★说明•目的防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。正确示例错误示例word=(high<<8)|lowif((a|b)&&(a&c))...if((a|b)<(c&d))・・・//合理使用括号增加可读性,//同时避免出现运算优先级的错误,正确。word=(high<<8)|lowif(a|b&&a&c)...if(a|b<c&d)...//没有使用括号,不但降低了可读性,//同时也出现了运算优先级错误。校对方法目视参考资料备注信息

第18条: 避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替。重要性难易度修改难度★★★★★★说明・目的宏和枚举可以使用英文单词,增加程序的可读性。而数字并没有表示和自我注释的能力。使用连续增值的宏定义时,应使用基础值递增的方法,或者使用枚举。正确示例错误示例♦defineMODE_ABS0♦defineMODE_T (MODE_ABS+1)♦defineMODE_ES (MODE_ABS+2)enumMODE_TYPE{mtAbs=OzmtTzmtEs};switch(g_iMode){caseMODE_ABS:break;caseMODE_T:break;caseMODE_ES:break;default:break;)switch(g_iMode){casemtAbs:break;casemtT:break;casemtEs:break;default:break;)//使用宏或枚举,正确。switch(g_iMode){case0:break;break;break;default:break;)//直接使用数字,大大降低了程序的可读性,错误。校对方法目视参考资料备注信息

变量和结构第19条: 仔细定义并明确公共变量的含义、作用、取值范围及公共变量间的关系。明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。重要性「难易度[修改难度★★★★说明•目的在对变量声明的同时,应对其含义、作用及取值范围进行注释说明,同时若有必要还应说明与其它变量和操作函数的关系,有利于程序的进ー步优化、单元测试、系统联调以及代码维护等。这种关系的说明可在注释或文档中描述。正确示例 错误示例//RELATIONSystemlnit InputRecordPrintRecordStatScore// //Student Create Modify Access Access//Score Create Modify Access Accessf Modify// 在源文件中,可按如上注释形式说明。RELATION为操作关系;Systemlnit>InputRecord、PrintRecord>StatScoreStudent、Score为两个全局变量;Create及示仓リ建,Modifエ衣示修改,Access表示访问。其中,函数InputRecord、StatScore都可修改变量Score,故此变量将引起函数冋较大的耦合,并可能增加代码测试、维护的难度。校对方法目视参考资料备注信息

第20条: 防止局部变量与公共变量同名。重要性难易度修改难度★★★★说明•目的若使用了较好的命名规则,那么此问题可自动消除。正确示例错误示例intg_iNum=0;voidGetItem(){intv_iNum;for(v_iNum=0;v__iNum<100;v_iNum++){…〃程序代码))//使用正确的命名规则使得局部变量与公共变量/Z很好识别。正确。intnum=0;voidGetItem()(intnum;for(num=0;num<100;num++){...//程序代码}}//没有使用正确的命名规则,容易导致局部变量与/Z公共变量产生混淆。错误!校对方法目视参考资料备注信息第21条:严禁使用未经初始化的变量作为右值。重要性难易度修改难度★★★★★说明・目的特别是在c/c++qr引用未经赋值的指针,经常会引起系统崩溃。正确示例错误示例intv_iNum=25;int*v_iPoint=&v_iNum;intv_iSum=*v_iPoint;/Z对变量初始化后在进行操作。正确。intv_iNum=25;int*v_iPoint;intv_iSum=*v_iPoint;/Z此处将会产生异常/Z指针变量没有就进行操作。错误!校对方法 目视参考资料备注信息

第22条: 构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象。重要性难易度修改难度★★★★★★★说明・目的这样可以降低公共变量耦合度。正确示例错误示例int*g_iKeyboardDevice;int*g—iMouseDevice;voidInitHardwareDevice()(g_iKeyboardDevice=newint[105];g_iMouseDevice=newint[3];}intGetKeyboardState(intKey){returng_iKeyboardDevice[Key];)intGetMouseState(intKey){returng_iMouseDevice[Key];)/Z全局变量的初始化与访问分开处理。正确。int*g_iKeyboardDevice;int*g_iMouseDevice;voidInitHardwareDevice()(g_iKeyboardDevice=newint[105];g_iMouseDevice=newint[3];)intGetKeyboardState(intKey)if(g-iKeyboardDevice==NULL)g_iKeyboardDevice=newint[105];returng_iKeyboardDevice[Key];)intGetMouseState(intKey)(if(g_iMouseDevice==NULL)g_iMouseDevice=newint[3];returng_iMouseDevice[Key];)/Z全局变量在多处被创建,虽然这样的代码在实际/Z工作中并不会产生多大的危害,但却大大降低了//程序的可维护性。错误!校对方法目视参考资料备注信息

第23条: 结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地(如预留一些空间等)。重要性难易度修改难度★★★★说明•目的软件向前兼容的特性,是软件产品是否成功的重要标志之一。如果要想使产品具有较好的前向兼容,那么在产品设计之初就应为以后版本升级保留一定余地,并且在产品升级时必须考虑前一版本的各种特性。正确示例错误示例typedefstructFILE_DATA_STRUCT{unsignedchartype;unsignedcharversion;unsignedintdate;charreserve[28];/Z保留字节,使结构//的大小保持为32/Z个字节。}FILEDATA//正确的使用保留字节,有助于今后的升级。正确。typedefstructFILE_DATA_STRUCTunsignedchartype;unsignedcharversion;unsignedintdate;}FILEDATA//没有使用保留字节,为今后的升级工作/Z帶来了不必要的麻烦。错误!校对方法目视参考资料备注信息

第24条: 编程时要注意数据类型的强制转换。重要性难易度修改难度★★★说明•目的当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。正确示例错误示例intv_iNum=2;floatv_rMax=(float)v_iNum/4.0;floatv_rResult=20.0/v_rMax;//正确的使用类型转换,可以防止异常产生。正确。intv_iNum=2;floatv_rMax=v_iNum/4;/Z此处对于不同的编译器可能会产成不同的结果//v_rMax有可能为0,这将给后面的计算带来麻烦。/Z错误!floatv_rResult=20.0/v_rMax;校对方法目视参考资料备注信息

函数与过程第25条: 对所调用函数的错误返回码要仔细、全面地处理,让函数的返回值有实际的意义。重要性 难易度[修改难度★★★ ★★★★说明•目的函数的返回值应有具体的说明。如果是状态返回值,应尽量使用宏或枚举。在检测返回值时应对各种情况进行判断,做到全面无遗漏。正确示例错误示例enumSTATUS_KEY{skOk=0,skErr,skOff};intCheckstatus()(・・・//程序代码}boolCheckOnOff(){・・・//程序代码}voidmain(){switch(Checkstatus())caseskOk:...//程序代码break;caseskErr:...//程序代码break;caseskOff:...//程序代码break;default:・・・ZZ程序代码break;}enumSTATUS_KEY{skOk=OzskErr,skOff};intCheckstatus()(...//程序代码}boolCheckOnOff()(...//程序代码}voidmain(){if(Checkstatus()==skOk)(...//程序代码}Else{...//程序代码}

if(CheckOnOff〇)(...//程序代码}else(...//程序代码})/Z对返回的状态有很好的管理机制。正确。if(CheckOnOff〇){...//程序代码}}II对返回值的判断不充足,不容易发现问题。错误!校对方法目视参考资料备注信息第26条: 编写可重入函数时,应注意局部变量和全局变量的使用(如编写C/C++语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。重要性难易度修改难度★★★★★★说明•目的重入函数就是可以同时被多个进程调用的函数。编写C/C++语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。正确示例错误示例intg_iNum=0;intGetSignalData(){staticboolv_bBusy=false;while(v_bBusy){.../Z判断超时}v_bBusy=true;.…〃有关g_iNum的程序处理代码intg_iNum=0;intGetSignalData()...//有关g_iNum的程序处理代码staticintv_iSum=0;for(inti=0;i<100;i++){v_iSum=v_iSum+SIGNALEDATA;}returnv_iSum;

v_bBusy=false;autointv_iSum=0;for(inti=0;i<100;i++){v_iSum=v_iSum+SIGNAL_DATA;}returnv_iSum;)//使用aut。或缺省态变量,防止重入错误。正确。//采用信号标志有效的保护币:入函数对全局变量/Z的改写。正确。}//没有采用信号标志对朮入函数进行保护,/Z很有可能造成对全局变量的运算错误。错误!//使用static变量,函数重入时将产生/Z无法预制的错误。错误!校对方法目视参考资料备注信息

第27条: 在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接口函数本身负责,缺省是由函数调用者负责。重要性 「难易度 「修改难度★★★★★★说明•目的对于模块间接口函数的参数的合法性检查这ー问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这ー必耍的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。正确示例错误示例voidGetSignalData(float*data)(*data=SIGNALEDATA;)voidmain(){...//程序代码if(g_rpData!=NULL){GetSignalData(g_rpData);})//在调用具有接u参数的函数前,由函数的调用/Z者负责检查参数的合法性。正确。voidGetSignalData(float*data)(*data=SIGNAL_DATA;}voidmain()(・・.〃程序代码GetSignalData(g_rpData);//如果g_rpData等于NULL,将产生异常)/Z调用者和被调用函数都没有进行参数合法性/Z检查,容易产生异常。错误!校对方法目视参考资料备注信息

重要性 难易度 修改难度★★★★★★说明•目的将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。正确示例错误示例voidGetSignalData(float*data){floatv_rResult=0;try(v_rResult=SIGNALEDATA;v_rResult=11.0592/v_rResult;*data=v_rResult;}catch(...){...//程序代码})//使用局部变量作为运算变量,最后对接口参数/Z进行负值。正确。voidGetSignalData(float*data)(try(*data=SIGNALEDATA;*data=11.0592/*data;//(1)}catch(...){...//程序代码}//一旦语句(1)产生异常,将会使data的值为//不可预知的状态。错误。校对方法目视参考资料备注信息

重要性 难易度 修改难度★★★★★★说明•目的函数在使用非参数输入之前,应进行必要的检查。正确示例错误示例int*g_ipNum;voidGetSignalData(int*Num){if(g_ipNum!=NULL)(…〃程序代码))/Z对全局变量进行合理性检查。正确。int*g_ipNum;voidGetSignalData(int*Num)(Num=SIGNAL_DATA;//(1))/Z没有检査全局变量的合理性。//语句(1)将有可能产生异常。/Z错误!校对方法目视参考资料备注信息第30条:让函数在调用点显得易懂、容易理解。重要性 难易度 修改难度★★★★★说明•目的增加程序的可读性,同时增加可插入的调试断点。正确示例错误示例intv_iNum;v_iNum=GetDeviceData();if(v_iNum==0)/Z此处可设置断点,观察{ //v_iNum的值...//程序代码)/Z函数调用清晰,为断点的插入提供了方便。正确。intv_iNum;if((v_iNum=GetDeviceData())==0)(...//程序代码}/Z函数调用隐蔽,无法设置断点观察变量值。错误!校对方法目视参考资料备注信息第31条: 当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。重要性难易度修改难度★★★★说明•目的这样可以增加编程效率和程序的可读性。正确示例错误示例♦defineFIRST_SOCKET_DATAReceiveBuffer[FirstSocket].byDataPtrif(FIRST_SOCKET_DATA){...//程序代码}//使用宏定义代替较长的数据访问。正确。if(ReceiveBuffer[FirstSocket].byDataPtr)(...//程序代码}//使用较长的数据访问使程序降低了可读性。//同时影响r程序的美观。错误!校对方法目视参考资料备注信息

2.7可测性第32条: 在同一项目组或产品组内,要有一套统ー的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号。重要性 难易度 修改难度★★★★★说明・目的本规则是针对项目组或产品组的,这样更能方便大家的联调。正确示例错误示例♦defineGLOBAL-TESTvoidmain()(intv_iNum;...//程序代码if(v_iNum==0){#ifdefGLOBAL_TESTprintf(''Thesignalresultis%d. Signal.cpp:125〃,v_iNum);#endifreturn;}...//程序代码}/Z对于联调测试提供相应的打印信息。正确。♦defineGLOBAL_TESTvoidmain()(intv__iNum;...//程序代码if(v__iNum==0){return;)...//程序代码)/Z没有为联调测试提供相应的打印信息。/Z这将增加联调的难度。错误!校对方法目视,编译调试。参考资料备注信息

第33条: 在编译器支持的情况下,使用断言来发现软件问题,提高代码可测性。重要性难易度ー修改难度★★★★说明•目的断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否则应报告),它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。正确示例#ifdefEXAM_ASSERT_TEST/Z若使用断言,测试voidexam_assert(char*file_namezunsignedintline_no)(printf(n\n[EXAM]Assertfailed:%s,line%u\nnzfile__namezline__no);abort();)defineEXAM_ASSERT(condition)if(condition)/Z若条件成立,则无动作NULL;else/Z否则报告exam_assert( FILE , LINE )else//若不使用断言测试defineEXAM_ASSERT(condition)NULLendif/*endofASSERT★/校对方法目视参考资料备注信息第34条: 用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度,而且统ー维护。调测开关应分为不同级别和类型。正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关掉)。重要性难易度修改难度★★★★★说明・目的避免因两套代码而产生的歧异。而且更加方便调试,己经生成更加精简的正式版。校对方法目视参考资料备注信息第35条: 在多重循环中,应将最忙的循环放在最内层。说明・目的减少cpu切入循环层的次数,ヵ当加程序的执行效率。正确示例错误示例for(col=0;col<5;col++){for(row=0;row<100;row++){sum+=a[row][col];))//将最忙的循环放在最里层。//CPU切入循环5次,达到最小。正确。for(row=0;row<100;row++)(for(col=0;col<5;col++)(sum+=a[row][col];}}/Z最忙的循环在外层。CPU切入循环100次,/Z无形中增加了CPU的负担。错误。校对方法目视参考资料备注信息修改难度★★★帀要性★★★难易度★第36条: 避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。重要性 难易度 修改难度★★★★★★说明・目的目的是减少判断次数。循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。正确示例错误示例if(data_type==RECT_AREA){for(i=0;i<MAX_NUMBER;i++){area_sum+=rect_area[i];))else{for(i=0;i<MAX_NUMBER;i++){if(data_type==RECT_AREA){area_sum+=rect_area[i];}else{length_sum+=rect[ind].length;for(i=0;i<MAX_NUMBER;i++){length_sum+=rect[i].length;width_sum+=rect[i].width;))/Z因为判断语句与循环变量无关,/Z应写成两种形式的循环。正确。width_sum+=rect[ind].width;))//在循环体内包含判断语句。增加了循环体的负担。错误!校对方法目视参考资料备注信息第37条: 尽量用乘法或其它方法代替除法,特别是浮点运算中的除法。重要性难易度修改难度★★★★★说明・目的浮点运算除法要占用较多CPU资源。正确示例错误示例♦definePI_RECIPROCAL(1/3.1416)/Z编译器编译时,将生成具体浮点数radius=circle_len*PI_RECIPROCAL/2;//将浮点数的除法转换为乘法。正确。#definePI3.1416radius=circle_length/(2*PI);//使用浮点数除法。增加了CPU的浮点计算。错误!校对方法目视参考资料备注信息

2.9质量保证第38条: 只引用属于自己的存贮空间,过程/函数中分配的内存,在过程/函数退出之前要释放,防止引用已经释放的内存空间,防止内存操作越界。重要性难易度修改难度★★★★★★说明•目的若模块封装的较好,那么一般不会发生非1而且在引用完毕,新分配的内存要释放文イ内存操作主要是指对数组、指针、内存地1果往往非常严里,所以当我们进行这些操イ去引用他人的空间。件句柄要关闭,而且也要防止引用已经释放的内存空间止等的操作。内存操作越界是软件系统主要错误之ー,后作时一定要仔细小心。正确示例错误示例♦defineMAX_USER10intGetUser(unsignedcharulndex){if(uIndex>=0&&uIndex<MAX_USER){returng_iUser[ulndex];}return-1;)/Z对数组的访问增加检测机制,防止越界。正确。♦defineMAX_USER10intGetUser(unsignedcharulndex){returng__iUser[ulndex];)/Z没有对数组的访问增加检测机制,//一旦越界,将产生无法预制的问题。错误!校对方法目视参考资料备注信息第39条: 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。重要性难易度修改难度★★★★说明・目的避免出现错误。校对方法目视参考资料备注信息第40条: 有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。重要性难易度修改难度★★★说明•目的防止由于疏漏而忽略的默认情况。正确示例if(n==0){.•.〃程序代码)else{一.//程序代码)switch(key){case0:・・・//程序代码case1:・・.//程序代码default:.・・//程序代码break;)校对方法目视参考资料备注信息

第41条: 在编写可移植程序时,不应使用与硬件或操作系统关系很大的语句。重要性难易度修改难度★★★★说明・目的使用建议的标准语句,以提髙软件的可移植性和可重用性。校对方法目视参考资料备注信息第42条: 除非为了满足特殊需求,避免使用嵌入式汇编。重要性难易度修改难度★★★★说明・目的程序中嵌入式汇编,一般都对可移植性有较大的影响。所以除非是调用非常频繁的,可以考虑用汇编让代码更加有效率,一般避免使用嵌入式汇编。校对方法目视参考资料备注信息第43条:为用户提供良好的接口界面,使用户能较充分地了解系统内部运行状态及有关系统出错情况。重要性难易度修改难度★★★★说明•目的错误信息要能够详细的说明出错的原因以及基本的解决办法。同时,为了能够使技术人员对问题进行详细的分析,错误信息中应包含错误代码。正确示例错误示例printf(''Error:Communicationtimeout.(%d)”,error_code);/Z错误信息中包含错误代码,方便解决问题。正确。printf(''Error.");/Z错误信息模糊,且无错误代码。错误!校对方法目视参考资料备注信息

第44条: 系统应具有一定的容错能力,对ー些错误事件(如用户误操作等)能进行自动补救。重要性难易度修改难度★★★★★★★★说明•目的例如对用户输入的数据进行计算时,应增加除零的判断或增加异常处理。正确示例错误示例inti;try(scanf(、ヽ%d",&i);printf 100/i);)catch(...){printf(''error./z);}/Z对用户输入数据进行除错处理。正确。inti;scanf(''%d",&i);printf(''%dz,,100/i);//i=0时将产生异常!//没有对用户输入数据进行除错处理。错误!校对方法目视参考资料备注信息第45条: 资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL文件或其它单独的描述文件(如数据库格式)重要性难易度修改难度★★★★★说明・目的方便对语言信息的修改。校对方法目视参考资料备注信息2.10代码的编译第46条:打开编译器的所有告警开关对程序进行编译。重要性难易度修改难度★★★说明•目的防止程序因为某些警告而产生无法预知的错误。校对方法目视参考资料备注信息第4フ条: 在产品软件(项目组)中,要统ー编译开关选项。重要性难易度修改难度★★★说明•目的提高整体调试的工作效率。校対方法目视参考资料备注信息第48条: 编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。重要性难易度修改难度★★★说明•目的保证数据的安全,避免不必要的损失。校对方法目视参考资料备注信息

第49条: 合理地设计和命名软件系统目录和源文件,方便开发人员使用。重要性难易度修改难度★★★说明•目的方便、合理的软件系统目录和源文件,可提高工作效率。目录构造的原则是方便有关源程序的存储、查询、编译、链接等工作,同时目录中还应具有工作目录——所有的编译、链接等工作应在此目录中进行,工具目录——有关文件编辑器、文件查找等工具可存放在此目录中。源文件的命名应该能够表示源文件中程序的作用和功能。示例工作目录:D:\Projects\Bin常规命名MainDef.c/MainDef.h存放类、结构、宏以及其他的类型定义。Main.c/Main.h存放主函数。GlobaLcZGlobal.h存放全局变量和变量初始化函数。Print.c/Print.h存放打印驱动函数。Rs232.c/Rs232.h存放串行通讯相关函数。Usb.c/Usb.h存放USB通讯函数。Compute.c/Compute.h存放数学计算相关函数。单片机Motor.c/Motor.h存放电机驱动函数。Lcd.c/Lcd.h存放液晶显示驱动函数。loBus.c/loBus.h存放总线输入/输出函数。lic.c/lic.h存放I2C通讯函数。PC机Query.cpp/Query.h存放数据查询相关界面和函数。SetQuery.cpp/SetQuery.h存放数据查询设置界面及相关函数。DataModeLcpp/DataModeLh存放数据库处理控件和相关函数。SocketDev.cpp/SocketDev.h存放网络通讯相关函数。Thread.cpp/Thread,h存放线程处理相关函数。校对方法 目视参考资料备注信息

第50条: 用宏定义表达式时,要使用完备的括号。重要性「难易度「修改难度★★ ★★★说明・目的避免由于运算符优先级而产生的错误。正确示例错误示例♦defineRECT_AREA(a,b)((a)*(b))/Z对整体加括号,对每个元素都加括号。正确。♦defineRECT_AREA(arb)a*b♦defineRECT__AREA(a,b)(a*b)♦defineRECT_AREA(a,b)(a)*(b)/Z只对局部加括号,没有考虑整体。错误!校对方法目视参考资料备注信息

重要性 难易度 修改难度★★★★说明•目的正确示例错误示例♦defineINTI_RECT_VALUE(a,b){a=0;b=0;)for(index=0;index<RECT_TOTAL_NUM;index++){INTI_RECT_VALUE(rect[index].a,rect[index].b);)/Z宏定义的多条表达式放在了{}中,正确。♦defineINTI_RECT_VALUE(a,b)a=0;b=0;for(index=0;index<RECT__TOTAL_NUM;index++){INTI_RECT_VALUE(rect[index].a,rect[index]・b);)/Z宏定义的多条表达式没有使用{},//因此,只有宏下面的・条语句有效。错误!校对方法目视参考资料备注信息

重要性难易度ー修改难度★★★★说明•目的正确示例错误示例♦defineSQUARE(a)((a)*(a))inta=5;intb;b=SQUARE(a);a++,//宏的参数没有发生变化。正确。♦defineSQUARE(a)((a)*(a))inta=5;intb;b=SQUARE(a++);/Z结果:a=7,即执行了两次增!.。错误!校对方法目视参考资料备注信息3,软件考核ー个成功的软件产品的诞生,一定要经过严格的检测。在软件的检验过程中,软件的编写者不能担任软件的测试者,但是软件的编写者要提供测试所需的必要文档。软件测试按照代码级审查,单元检验,集成检验的步骤进行。测试期间的所有测试用例均应保存,以保证测试具有可重复性。规范考核这个部分的考核,主要考核代码的编写质量,主要注重的是规范,而不是软件的实际功能进行的考核。在这个阶段的考核中,为了加快考核者的效率,代码作者需提供详细的代码说明书,包括全局变量说明,设计流程图,重要速据流程图,函数和控件的接口规范,以及ー些实现代码说明。检测者通过仔细阅读代码作者提交的说明,依照本文第二节的编程规范进行代码的考核,最后出具写代码检测报告(表1为编程规范中具体分值分配)。表1编程规范考核分值分配表(总分100)模块测试本阶段的测试要以査找错误为中心,而不是为了演示软件和模块的正确功能。而且在本测试中,合格的软件要通过所有的测试,故不采取评分制度,而且进ー步划分为下面2个阶段:单元测试单元测试主要是在编程规范考察的基础上,进ー步对代码中的各个模块单元进行测试,任务包括:模块接口测试、模块局部数据结构测试、模块中所有独立执行通路测试、模块的各条错误处理通路测试、模块边界条件测试;测试方法主要白盒测试,而且对于单个的功能,可以编写小的测试例程,其具体测试如下:•模块接口测试测试项模块接口测试测试目的测试模块的数据是否能正确的流入,流出。测试方法白盒测试,可以编写例程进行测试测试标准.输入的实际参数与形式参数的个数和属性相匹配:.调用与被调用模块之间所给实际参数的个数和属性相匹配;.调用其他模块时所给实际参数的属性与被调模块的形参属性匹配;.调用其他模块时所给实际参数的量纲与被调模块的形参量纲一致;.调用预定义函数时所用参数的个数、属性和次序正确;6,没有修改了只读型参数;.缓冲区大小与记录长度相匹配;.处理了输入/输出错误;.输出信息中没有有文字性错误;

•检査局部数据结构测试项检查局部数据结构测试目的保证临时存储在模块内的数据在程序执行过程中完整、正确。测试方法白盒测试,目测测试标准.变量类型声名合适;.变量初始化无错误;.没有出现地址的溢出:.全局变量使用正确;•独立执行路径测试测试项独立执行路径测试测试目的发现因错误计算、不正确的比较和不适当的控制流造成的错误。此时基本路径测试和循环测试是最常用且最有效的测试技术。测试方法白盒测试,编写例程测试测试标准.没有因为运算符优先级造成的错误;.计算中没有出现因为类型转换而造成的精度损失;3,没有硬件的原因造成精度不够;.循环终止条件总会出现;.迭代发散时能退出;.循环变量操作正确。•出错处理测试测试项出错处理测试测试目的检验程序是否能遇见各种错误而且能正确的处理。测试方法白盒测试,编写例程测试,人工制造错误。测试标准.输出的出错信息正确且易理解;.在出现错误时,系统能最优的处理错误;.异常处理恰当:.错误陈述中提供足够的定位出错信息。•边界条件测试测试项边界条件测试测试目的针对边界值及其左、右设计测试用例,尽可能发现新的错误。测试方法白盒测试,编写例程测试,输入程序处理的边界值测试标准.在输入边界值的情况下,程序也能正确处理。.在输入边界外的值的情况下,程序能正确报错。集成测试集成测试主要是测试大的功能模块的功能,而不是重点考虑单个函数的功能,使其基本能完成软件需求的部分功能,测试方法是白盒测试结合黑盒测试方法,而且在测试过程中,应有代码编写者提供合适的测试用例。主要考察下面的功能:.没有出现资源调用冲突;.模块的功能很完善;.模块和模块之间的接口设计合理;测试方法一般采用自底向上测试,从“原子”模块(即软件结构最低层的模块)开始组装测试,因测试到较高层模块时,所需的下层模块功能均已具备。自底向上综合测试的步骤分为:.把低层模块组织成实现某个子功能的模块群(cluster);.开发ー个测试驱动模块,控制测试数据的输入和测试结果的输出;.对每个模块群进行测试;.删除测试使用的驱动模块,用较高层模块把模块群组织成为完成更大功能的新模块群。从第一步开始循环执行上述各步骤,直至整个程序构造完毕。3.3功能测试这个部分的测试,依据公司软件的特点,・般情况是通过连接仪器进行联机测试,测试的指标也主要是是否能满足公司仪器所需要的功能,主要依据是产品组的软件需求说明书。合格的产品要通过此项全部测试。测试方法主要是黑盒测试,也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因ー果图、错误推测等,主要用于软件确认测试。“黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论