CPS软件C语言编码规范_第1页
CPS软件C语言编码规范_第2页
CPS软件C语言编码规范_第3页
CPS软件C语言编码规范_第4页
CPS软件C语言编码规范_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

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

文档简介

正泰电源内部文件禁止外传软体C语言编码规范文件编号版本编制日期页数CPS-WI-RD0019.V01

V022016-06-0322NUM拟制:签名:日期:审核:经理/总监签名:日期:审核:经理/总监签名:日期:审核:经理/总监签名:日期:审核:经理/总监签名:日期:审核:经理/总监签名:日期:批准:总经理签名:日期:

目录TOC\o"1-2"\h\z\u更改历史记录 21、 总论 31.1目的 31.2 范围 31.3 参考资料 31.4定义 31.5职责 32、规范内容 42.1 程序结构布局 42.2 程序的排版 72.3 注释 92.4 命名规则 112.5 变量的使用 132.6 表达式 142.7 函数 172.8 预编译/宏(Macro) 193、记录相关文件表单、流程图 193.1附录一:常用单词的缩写 203.2附录二:变量的常用前缀缩写 203.3附录三:常见常量的缩写形式 20总论1.1目的软件编程规范的目的和意义在于:1.1.1.统一公司嵌入式C语言软件编程风格1.1.2.提高软件源程序的可读性、可靠性和可重用性1.1.3.提高软件源程序的质量和可维护性1.1.4.减少软件维护成本,最终提高软件产品生产力范围本文是针对整个ChintPower嵌入式C语言编程而制定的编码规范。参考资料**********1.4定义1.4.1.本文中,对于每一项规则和建议,将采用如下的概念表达方法:1.4.1.1.首先给出规则或者建议简要的文字描述。1.4.1.2.然后给出在要点基础上延伸的说明文字。1.4.1.3.最后给出示例。给出正面例子,作为模版或文字描述的具体展示;或者给出反面例子,提示大家不要在编码过程中出现类似情况。1.4.2.本文中使用的术语解释如下:1.4.2.1.规则:编程时必须遵守的约定,规则项将会作为SQA的稽核内容。1.4.2.2.建议:编程时必须加以考虑的约定。1.4.2.3.说明:对此规则或建议的必要的解释。1.4.2.4.正例:对此规则或建议给出的正确例子。1.4.2.5.反例:对此规则或建议给出的反面例子。1.4.3.本规范分为规则性和建议性两种:对于规则性规范,要求所有软件开发人员严格执行;对于建议性规范,各项目编程人员可以根据实际情况选择执行。1.4.4.由于规则是用来说明一般情况的,所以每条规则都是在一般情况下才有意义。如有特例需要违反规则,必须添加注释予以说明!1.5职责本文之核准、修改、发行、依文件管理准则********处理。2、规范内容 2.1 程序结构布局2.1.1.目录结构【规则1-1】同类软件工程项目,遵循统一的工程结构。【说明】根据INVERTER工程需要和公司习惯,INVERTER软件工程结构如下所示,对于某些目录,如:+support就可根据使用的编译器环境确定是否存在,或者是否存在其他目录配置文件。Project +app 应用层代码(Task,Interrupt)+kernel RTOS源代码 +include 所需要包含的头文件 +module 软件模组 +driver 设备驱动程序+cpu 存放CPU相关的宏(I/0,Register定义) +output 存放最终的目标文件 +debug 存放.obj文件等编译器产生的文件 +cmd 存放编译器配置文件 其他工程配置文件【规则1-2】在整个工程范围内调用的变量和函数(公用部分)声明放在头文件中,文件范围内调用的变量和函数(私有部分)声明放在本文件的前面,函数范围内调用的变量声明在函数体的开头。【说明】为更好的进行信息隐藏,将模块进行封装,降低不同模块之间的耦合度,方便程序的维护和重用,公用部分的声明放在头文件当中,私有部分的声明放在源文件当中。2.1.2.文件布局【规则1-3】遵循统一的布局顺序来书写头文件(*.h)。【说明】头文件由三部分组成:版权和版本声明;预处理块;常数、变量以及函数等声明。版权和版本的声明位于头文件和定义文件的开头,主要内容包括:(1)版权信息;(2)文件名称、标识符、摘要;(3)当前版本号、作者/修改者、完成日期;(4)版本历史信息。预处理块的作用是为了防止头文件被反复引用,因此,必须使用ifndef/define/endif结构产生预处理块。头文件的所有声明须遵循下面的顺序:常量->全局宏—>全局数据类型->外部引用->全局函数原型。【正例】下面的代码是一个完整的头文件模版,请依照下面的顺序进行书写:/*********************************************************************Copyright2009,ChintPower.FileName: Example.hDescription: ThisfileshowsastandardheadfileformatVersion: V1.0Author: NAME_EXPDate: 2009-10-19*********************************************************************///preprocessblock#ifndefMODEL_H#defineMODEL_H//constantdefinition#defineeUtilityTimer 0//GlobalMacro#definemGetExtIoBit(bit)((uwExtBuf0[0]&(1<<(bit)))>>bit)//globaldatatypeTypedefstruct{ INT8SbName[10];INT16UuwAge; }STUDENT;//externalreferenceExternINT16UuwInvVoltSampCnt;//globalfunctionprototypevoidsPowerOnMode(void);voidsStandbyMode(void);voidsBypassMode(void);#endif

【规则1-4】遵循统一的布局顺序来书写源文件(*.c)。【说明】定义文件由三部分组成:版权和版本声明;对头文件的引用;数据和代码。版权和版本的声明位于文件的开头,主要内容包括:(1)版权信息;(2)文件名称、标识符、摘要;(3)当前版本号、作者/修改者、完成日期;(4)版本历史信息。数据和代码部分必须遵循下面的顺序:常数和宏定义->数据类型声明->变量声明->表->函数原型->全局函数->局部函数。【正例】下面的代码是一个完整的定义文件模版,按照下面的顺序进行书写:/*********************************************************************Copyright2008,SANTKCorporation.FileName: Example.cDescription: ThisfileshowsastandardsourcefileformatVersion: V1.0Author: NAME_EXPDate: 2009-10-19*********************************************************************//****head-filesincluding****/#include"kernel\kernel.h"#include"module\module.h"/****macrodefinition****/#definecSciTxRdy0#definecSciTxBusy1…………/****datatypedefinition****/typedef void(*pFunc)(void);typedef int(*pFunc1)(void);typedef void(*pFunc2)(unsignedint);typedef INT16U(*pFunc3)(void);…………/****variabledefinition****/INT16S wCmdLength;INT8U *pubCmdIn0;INT8U *pubCmdIn1;…………/****table****/constINT8S bCmdTabArray[MAX_CMD_SIZE][2]={"AG","AS","CT","CV","EX","FS","LS","ON", "PF","PS","PW","Q1","Q2","Q3", "Q7","QD","QM","QP","VS","WA","WH"};…………/****functionprototype****/INT8UsubSnatchGraph(void);voidsTestCmd(void);…………/****globalfunction****//*********************************************************************Functionname: INT8UsubSnatchGraph(void)Description: SaveINVERTERinternalvariantvalueCalls: CalledBy:INVInterrupt()Parameters: voidReturn: INT8U*********************************************************************/INT8UsubSnatchGraph(void){ …..}/****localfunction****//*********************************************************************Functionname: voidsTestCmd(void)Description: testcommandforsci.Calls: sSetBatTestTime();CalledBy:Parameters: voidReturn: void*********************************************************************/voidsTestCmd(void){ …………}2.1.3.文件容量『建议1-1』每个源程序大小应控制在3000LOC以内。2.2 程序的排版版式虽然不会影响程序的功能,但会影响可读性。程序的版式追求清晰、美观,是程序风格的重要构成因素。2.2.1.空白行使用【规则2-1】文件之中不得存在无规则的空行,函数与函数之间的空行为2行,在函数体内部,在逻辑上独立的两个语句块可适当空行,一般为1行。2.2.2.语句中的空格【规则2-2】函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。【规则2-3】‘(’向后紧跟,‘)’向前紧跟,‘;’向前紧跟,紧跟处不留空格,但和后面内容留有一个空格,‘,’前后紧跟。【说明】向后紧跟即与后面的内容直接无空格,向前紧跟即与前面的内容无空格,前后紧跟说明与前后的内容都无空格。【正例】for(i=0;i<cMaxNum;i++){sModelFunction(bParameterA,bParameterB);}【规则2-4】二元操作符的前后必须添加空格。【说明】二元操作符包括:赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符。如“=”、“+=”“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等。【规则2-5】一元操作符前后不加空格。【说明】一元操作符包括“!”、“~”、“++”、“--”、“&”(地址运算符)“[]”、“.”、“->”这类操作符。【规则2-6】必须将修饰符*和&紧靠变量名,而不是靠近数据类型名。【正例】INT16U*puwVariableA;【反例】INT16U*puwVariableA;2.2.3.语句中的缩进【规则2-7】统一使用4个字符的缩进,并使用空格代替TAB键。【规则2-8】程序的分界符‘{’和‘}’必须独占一行并且位于同一列,同时与引用它们的语句左对齐;{}之内的代码块在‘{’下一行的右边四个空格处对齐。【规则2-9】对于单条语句的注释,且注释内容不超过1行的情况下,可以在语句之后进行行注释。对于需要在代码上方添加的注释,应保证注释与代码必须保持相同的缩进。【正例】标准的写法是://judgeifinverterperiodisinnoise,yes,updaterelevantvariable,no,return.if(wInvPrdNewTemp<cPrd200Hz){….}wInvPrdNew=wInvPrdNewTemp;//updatecrosszerovalue……2.2.4.代码行【规则2-10】代码行长度必须控制在80个字符以内(含空格)。【规则2-11】if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都必须要加{}。【反例】if的执行语句紧跟其后:if(pCanRxIn==&wCanRxBuf[cCanRxBufSize-1])pCanRxIn=wCanRxBuf;【正例】虽然执行语句只有一行,但仍然要加“{}”,if语句自占一行:if(pCanRxIn==&wCanRxBuf[cCanRxBufSize-1]){pCanRxIn=wCanRxBuf;}【规则2-12】长表达式(超过80个字符)要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符);拆分出的新行要进行缩进,使排版易读、整齐。【正例】长赋值语句拆分:dwPFCTemp=(INT32S)((INT32S)wKvd_1*wVm_P\ +(INT32S)wKvd_2*wVm_P_1+(INT32S)wKvn_1*wVerr_P\ +(INT32S)wKvn_2*wVerr_P_1+(INT32S)wVm_P_Res);长判断语句拆分:elseif((swGetPBusAvgVoltNew()>cBus120v)\&&(swGetNBusAvgVoltNew()>cBus120v)\&&(wPreChgCnt>=500))【规则2-13】一行代码只做一件事情,如只定义一个变量,或只写一条语句。【说明】也就是说一行代码只允许有一个语句;不能在一行代码同时定义多于一个的变量。 这样做的目的是为了使代码便于阅读和注释。2.3 注释注释应该和编码同步,并保持和代码的一致。C语言的块注释符为“/*”“*/”,行注释符用“//”。注释的内容通常有:(1)版本、版权声明;(2)函数接口说明;(3)重要代码行、段落意义说明。2.3.1.注释语言【规则3-1】注释必须使用英文,且注释要言简意赅。2.3.2.文件头部注释【规则3-2】文件头部必须进行注释,包括:.h文件、.c文件、.cpp文件等。【说明】文件头部注释应包含的基本内容如下:Copyright:Filename:Description:Author:Version:Date:【正例】/*********************************************************************Copyright2009,ChintCorporation.FileName: Linemodule.hDescription: definefunctionnameVersion: V1.0Author: NAME_EXPDate: 2009-10-19*********************************************************************/2.3.3.函数头部注释【规则3-3】函数头部要给出的注释包括:函数名称、功能、输入参数、输出参数、返回值、调用说明、修改历史,其中函数名和描述必须要写,其他项可根据函数实体的实际情况而定。【说明】函数头部注释应包含的基本内容如下:Functionname:Description:Calls:CalledBy:Parameters:Return:【正例】/*********************************************************************Functionname: INT8UsubSnatchGraph(void)Description:SaveINVERTERinternalvariantvalueCalls: CalledBy:PFCInterrupt()Parameters:voidReturn: INT8U*********************************************************************/2.3.4.全局变量注释【规则3-4】全局变量必须进行注释,内容一般包括:功能、取值范围、访问信息、注意事项。对于不能充分自注释的局部变量,也应该要加注释予以说明。【正例】//RealvoltageofR,S,Tphase,andiscalledbyinterruptINT16UuwRLineVoltReal=0;INT16UuwSLineVoltReal=0;INT16UuwTLineVoltReal=0;2.3.5.语句注释【规则3-5】在功能相同的语句段前添加注释说明该段语句的功能。【正例】//updatecrossingzerovaluewInvPrdNew=wInvPrdNewTemp;wInvPrdCntNew=wInvPrdCntNewTemp;wInvZeroTimeNew=wInvZeroTimeNewTemp;wInvZeroTimeOld=wInvZeroTimeNew;【规则3-6】对于多层嵌套、多个分支的语句块必须进行注释。【说明】这些语句往往是理解一段代码的关键,因此,必须进行清晰的注释,对于软件工程师来说,读这些注释要比读开发文档的效果好得多。【正例】下面这段代码是一个if条件判断语句块,里面又有多层嵌套,因此,必须进行清晰的注释。如下所示,在每一个嵌套部分对功能进行描述。//checkifpqisfullif(pq->length==pq->size){//whenfullqueuewillcoverthefrontofqueue.if(cOverWrOpt==QUE_COVER_FIRST) { *(pq->pIn)=data;//checkifpInpointedtothetailofqueue if(pq->pIn==pq->pStart+pq->size) { pq->pIn=pq->pStart; } else { pq->pIn++; } pq->pOut=pq->pIn; }//whenfulldatawillcoverthelastofqueueelseif(cOverWrOpt==QUE_COVER_LAST) { //checkifpInpointedtotheheadofqueueif(pq->pIn==pq->pStart) { *(pq->pStart+pq->size)=data; } else { *(pq->pIn-1)=data; } } return(QUE_BUF_FULL);}2.3.6.修改程序注释【规则3-7】修改标签采用统一的格式://Modifiernameyyyymmdd+附加说明【正例】单独行修改标签:INT16SwTemp; //panna20080130段修改标签://panna20080130beginstructBOX{INT16Si; INT16Sj; INT16SwLength; INT16SwWidth; };//panna20080130end2.3.7.其他建议『建议3-1』注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱。注释的花样要少。『建议3-2』发布release版本时应删除无用的注释和测试代码。2.4 命名规则公司的命名规则遵守匈牙利命名法,该命名规则的主要思想是“在变量和函数名中加入前缀以增强人们对程序的理解”。2.4.1.常量命名【规则4-1】有意义的常数需要用常量来表示,以增强可读性,常量需要以小写c开头。常用缩写见HYPERLINK附录1。『建议4-4』对于无符号的变量前面加u,用以区别有符号的变量。【说明】要对无符号的变量与有符号的变量、常量加以区分,就应该添加某些前缀。如unsignedbyte:ubunsignedword:uw unsigneddoubleword:udw而有符号的变量前面不加u,用以跟无符号的变量、常量区分。如signedbyte:bsignedword:wsigneddoubleword:dw2.5 变量的使用2.5.1.变量的使用【规则5-1】定义变量时,必须明确其含义、作用、取值范围,以及同其他变量之间的关系。【反例】INT8U ubLineZeroCnt;for(ubLineZeroCnt=0;ubLineZeroCnt<300;ubLineZeroCnt++){………}结果会导致变量ubLineZeroCnt发生越界现象。因此,在定义变量的时候应该首先明确该变量的取值范围,如本例中,需要将INT8U ubLineZeroCnt;改为INT16UuwLineZeroCnt;【规则5-2】编写可重入函数时,若使用全局变量,必须使用关中断,信号量等手段对其加以保护。【说明】如果不对全局变量加以保护,则此函数就不具备可重入性,在多个进程调用该函数时,很有可能使有关全局变量的值发生预料之外的改变。【正例】OS_ENTER_CRITICAL();//closeglobalinterruptuwDroopStatus=cDroopBypass;OS_EXIT_CRITICAL();//openglobalinterrupt【规则5-3】严禁使用未经初始化的变量作为右值,尤其是指针变量。【说明】任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。【规则5-4】构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象。【说明】降低系统中全局变量之间耦合度。可以避免访问全局变量时的错误操作。例如使用统一的Get和Set函数对一系列全局变量进行“读”和“写”的操作。【正例】利用函数swGetRLineVolt来获取变量wRLineVolt的值。INT16S swGetRLineVolt(void){ return(wRLineVolt);}【规则5-5】对于有数据类型转换的赋值,必须要进行强制的数据类型转换,避免隐式的数据转换。【说明】对于有要数据类型转换情况,一定要使用(数据类型)数据的方式进行转换。【反例】wRInvVoltSample=((INT32S)wRInvVoltSample*wADCCoefA)>>14;wRInvVoltSample为INT16S型的,而((INT32S)wRInvVoltSample*wADCCoefA)>>14产生的结果为INT32S型,会造成隐形的数据转换。【正例】为了避免上面的隐形数据转换,应该用如下的强制数据转换来转换结果:wRInvVoltSample=(INT16S)(((INT32S)wRInvVoltSample*wADCCoefA)>>14);2.5.2.其他建议『建议5-1』只在文件范围内使用,具有整个生命周期的变量需要加上static限定2.6 表达式C语言的运算符有数十个,运算符的优先级与结合律如表6-1所示。注意一元运算符+-*的优先级高于对应的二元运算符。表6-1运算符的优先级和结合律优先级运算符结合律从高到低排列()[]->.从左至右!~++--(类型)sizeof+-*&从右至左*/%从左至右+-从左至右<<>>从左至右<<=>>=从左至右==!=从左至右&从左至右^从左至右|从左至右&&从左至右||从右至左?:从右至左=+=-=*=/=%=&=^=|=<<=>>=从左至右,从左至右2.6.1.复合表达式【规则6-1】在有多个不同类型运算符的表达式中,必须使用括号对运算优先级进行限制,避免使用默认的优先级顺序。【说明】虽然C语言规定了各种运算符之间的优先级顺序,但是,每个人都对该顺序熟烂于心是不可能的。因此,为了保证正确性也提高代码的可读性,在表达式中有多个不同类型运算符的时候,必须使用括号来限制优先级。【正例】下面的运算式包含了减法、乘法、移位、强制类型转换四种运算:wLnPrdNewTemp=(INT16S)(((INT32U)(wLineZeroTimeNewTemp–wLineZeroTimeOld)*27962)>>16);//calculatelinevoltageperiod【规则6-2】对于涉及到除法运算的表达式,一定要校验除数表达式(或变量)是否为0;对于涉及到取余运算的表达式,一定要校验运算符两边的数是否为整数。2.6.2.if表达式【规则6-3】布尔变量只应该和FALSE进行比较。【说明】TRUE和FALSE的定义值是与语言环境相关的,是可以被重定义的。本规则正例中的格式只适用于布尔类型的变量或表达式与0比较的情况。【正例】假设ubTest为布尔型变量,判断ubTest的值用下面的表达式:if(ubTest==FALSE)//表示判断ubTest是否为假if(ubTest!=FALSE)//表示判断ubTest是否为真【规则6-4】不可以将浮点型变量用“==”或“!=”与任何数值进行比较。【说明】float和double类型的变量都有精度的限制,因此,不能直接用来同数值进行等于或不等于的比较,应设法转化为大于并且小于某一个精度范围。【规则6-5】指针型变量与零值的比较应该和NULL进行比较。2.6.3.for循环语句【规则6-6】不可以在for循环体的内部修改循环变量,防止for循环失去控制。【说明】for循环内部的循环变量不可在循环语句外部进行修改操作,如果操作不当可能会导致该循环不可控制,使得循环失效。【反例】for(I=0;I<128;i++){*Dest++=*Source++; i++;//maybeletthecycleuncontrollable!}2.6.4.switch语句【规则6-7】switch语句中的每个case块必须有break,否则不同case块会重叠;switch语句中的default块不可以省略,default块也必须有break语句。【说明】漏掉break语句会造成程序错误。多个分支语句处理同一种情况的时候,即需要case块的重叠时,可以去掉break,但必须有注释说明。【正例】switch(uwFanDetectCnt){case0: sClrFanClkCnt(); break; case100: sFan0LockChk(suwGetFanClkCnt(),230,5); break; case1250: sClrFanClkCnt(); break; case1350: sFan1LockChk(suwGetFanClkCnt(),230,5); break; default: break;}2.6.5.其它建议『建议6-1』循环变量的取值范围设置为半开半闭区间。【说明】当循环变量的取值范围设置为半开半闭区间时,循环的次数就是两个值的差值,使程序易读并且不容易出错。【正例】下面的例子中,循环变量i的循环条件为I<wLength,而不是I<=wLength,这样wLength的值就是循环的次数。for(I=0;I<wLength;i++){*(puwDestBuf++)=*(puwSourceBuf++);}如果将循环条件改为I<=wLength,那么循环的次数为wLength+1,阅读时容易出错。『建议6-2』建议使用条件判断的嵌套层数不大于5层。『建议6-3』使用简单的复合语句,不要使用太复杂和多用途的复合语句。『建议6-4』for语句需要拆分时可拆分为三行。『建议6-5』当使用永久循环时,尽量使用“While(1)”代替“for(;;)”『建议6-6』避免用do/while,可用While与break代替。『建议6-7』在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨循环层的次数。2.7 函数2.7.1.参数规则【规则7-1】参数的书写要完整,不能只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。参数的个数要尽量控制在5个以内。【说明】书写完整,不能省略参数名;命名要合理,即明确表达出参数的作用;更有利于程序的可读性顺序要恰当,即一个函数有多个参数的时候,顺序要遵循程序员的习惯,例如输入参数放在前面,输出参数放在后面。【正例】voidsCanCopy(CANFRAME*pSource,CANFRAME*pDestination)输入参数为source,输出参数为destination。【规则7-2】如果参数是指针,且仅作输入用,则必须在类型前加const,以防止该指针在函数体内被意外修改。【正例】VoidsBatUnderVoltSetVSLoad(constINT16U*puwBatUnderPointsTable,INT16UuwLoadLevel1,INT16UuwLoadLevel2)指针变量puwBatUnderPointsTable在这里仅作为输入作用,为防止该值在使用过程中被意外改变,应该加const修饰。【规则7-3】当结构变量作为参数时,应传送结构的指针而不传送整个结构体。【说明】一个函数被调用的时候,形参会被一个个压入被调函数的堆栈中,在函数调用结束以后再弹出。一个结构所包含的变量往往比较多,直接以一个结构为参数,压栈出栈的内容就会太多,不但占用堆栈空间,如果使用不当还可能导致堆栈的溢出,而且影响代码执行效率,。但是使用结构的指针作为参数,由于指针的长度是固定不变的,结构的大小就既不会影响代码执行的效率,也不会过多地占用堆栈空间。【反例】VoidsCanCopy(CANFRAMEstSource,CANFRAMEstDestination)【正例】VoidsCanCopy(CANFRAME*pstSource,CANFRAME*pstDestination)2.7.2.返回值规则【规则7-4】返回值的类型不能省略。【说明】在C语言中,返回值的类型没有被定义时,默认为整型,但是从写法上,容易被误认为是void类型,会引起不必要的麻烦,所以,函数的返回值类型不能省略。【反例】sQInit(QUEUE*pstPq,INT8U*pubStart,INT16UuwSize)返回类型系统默认为整型;【正例】voidsQInit(QUEUE*pstPq,INT8U*pubStart,INT16UuwSize)返回类型为空;因此,函数的返回值为空时也不能省略。【规则7-5】对于有返回值的函数,函数的每一个分支都必须有返回值。【说明】防止出现函数无值返回,造成返回值的不可预知性。【反例】INT8UsubSciGetRxData(INT8UubSciid){if(ubSciid==0){ return(subGetSciRxData0()); } if(ubSciid==1) { }}【正例】INT8UsubSciGetRxData(INT8UubSciid){ if(ubSciid==0) { return(subGetSciRxData0()); } if(ubSciid==1) { return(subGetSciRxData1()); }return(0);}【规则7-6】不要返回函数内堆栈内存的指针。2.7.3.函数内部规则【规则7-7】禁止将函数的参数作为工作变量。【说明】如果将函数的参数作为工作变量,那么参数内容在函数体内会被改变,所以很危险。对必须改变的参数,最好先用局部变量作为工作变量,处理结束后,将该局部变量的内容在最后赋给该参数。2.7.4.其它建议『建议7-1』不要使用类型和数目不确定的参数。『建议7-2』尽量在文件中仅包含该文件用到的头文件。『建议7-3』函数的规模控制在200行以内。【说明】200行不包括注释和空格行。『建议7-4』函数的功能是可预测的,即每种输入产生确定的输出。2.8 预编译/宏(Macro)【规则8-1】用宏定义表达式时,要使用完备的括号,必要时使用大括号。【说明】当宏带有变量的时候,由于宏是简单的替代,如果没有完备的括号,宏是存在风险的。另外,当宏包含的语句不止一句的时候,必须使用大括号把语句块包含起来。【正例】完备的括号:#definemGetExtIOBit(bit)((uwExternalBuf[0]&(1<<(bit)))>>(bit))多条语句(注意换行符“\”的使用):#definemWriteExtIO0(iset)\{\outportbuffer0=(iset);\uwExternalBuf[0]=outportbuffer0;\}【反例】不完备的括号:#definemGetExtIOBit(bit)(uwExternalBuf[0]&(1<<(bit)))>>(bit)多条语句:#definemWriteExtIO0(iset)outportbuffer0=(iset);uwExternalBuf[0]=outportbuffer0【规则8-2】调用宏时,不允许宏参数发生变化【说明】当宏的参数不止一次被带入计算,那么第二次替代时,参数值已经被改变,将得不到需要的结果。【反例】#definemSQUARE(a)((a)*(a))inta=5;intb;b=mSQUARE(a++);结果:a=7,即执行了两次增1。【正例】b=mSQUARE(a);a++;结果:a=6,即只执行了一次增1。【规则8-3】在程序开头,为编译控制符编写#define与#undef语句。【规则8-4】在#include指示符中,不得使用绝对路径,允许自动编译选择。【说明】在编译器环境中设定绝对路径,程序中需要使用相对路径包含头文件。【正例】#include“Kernel\OS_HEAD.H”,在编译器中设置绝对路径:D:\testc\SplitPhaseDriver。【反例】使用绝对路径包含头文件#include“D:\test

温馨提示

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

最新文档

评论

0/150

提交评论