版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言代码编程规范2010.7.23C语言代码编程规范2010.7.2311概述1.1、目的1.2、说明与适用范围1.3、术语解释1.4、代码编码基本原则1概述1.1、目的21.1目的提高代码质量提高程序的可移植性和可维护性提高程序的可靠性、可读性、可修改性和可继承性避免危险结构减少对个体程序员的依赖形成统一的开发风格,产生一致的代码,增进团队协作1.1目的提高代码质量31概述1.1、目的1.2、说明与适用范围1.3、术语解释1.4、代码编码基本原则1概述1.1、目的41.2
说明与适用范围说明:
本规范同时适用与C编码和汇编编码,其中有一些是C特有的,汇编编码不需要遵循适用范围
本规范适用于软件部门的所有用C语言开发的项目1.2说明与适用范围说明:51概述1.1、目的1.2、说明与适用范围1.3、术语解释1.4、代码编码基本原则1概述1.1、目的61.3
术语解释术语解释单边作用(sideeffect):指在表达式执行后对程序运行环境可能会造成影响。赋值语句、自增操作等都是典型的具有单边作用的操作。1.3术语解释术语解释71概述1.1、目的1.2、说明与适用范围1.3、术语解释1.4、代码编码基本原则1概述1.1、目的8程序的编码一般应考虑下列原则:
1.编制易于修改和维护的代码。
2.编制易于测试的代码:运用条件编译语句尽早设计出测试用例,采用统一的命名规则管理这些测试用例并适时地进行回归测试等一系列措施。 3.必须将编程与编文档的工作统一起来:这样既有利于整个项目按期完成,又能保证文档与程序协调一致。1.4代码编码基本原则程序的编码一般应考虑下列原则:1.4代码编码基本原则91.4代码编码基本原则4.编程中采用统一的标准和约定,降低程序复杂性,慎用Goto语句、慎用嵌套等。5.限定每一层的副作用,减少耦合程度:主要技术是分解。6.尽可能地重用。
1.4代码编码基本原则4.编程中采用统一的标准和约定,降102代码规范C语言代码规范架构1排版9数据冗余2注释10程序效率3标识符11指针4变量和数据类型12Switch语句5声明和定义13预处理6函数14结构体与联合7控制流和表达式2代码规范C语言代码规范架构1排版9数据冗余2112.1.1空格的使用:
在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格.逗号、分号只在后面加空格比较操作符,赋值操作符,算术操作符,逻辑操作符,位域操作符等双目操作符的前后加空格"!"、"~"、"++"、"--"、"&"(地址运算符)等单目操作符前后不加空格“->”、“.”前后不加空格if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。
2.1排版2.1.1空格的使用:2.1排版122.1排版2.1.2文件之中不得存在无规则的空行,比如说连续十个空行。
2.1.2if(!valid_ni(ni)){...//programcode}repssn_ind=ssn_data[index].repssn_index;epssn_ni=ssn_data[index].ni;2.1.2if(!valid_ni(ni)){...//programcode}repssn_ind=ssn_data[index].repssn_index;epssn_ni=ssn_data[index].ni;2.1.3相对独立的程序块之间、变量说明之后必须加空行。错误示例:正确示例:2.1排版2.1.2文件之中不得存在无规则的空行,比如132.1排版2.1.4一行程序不能大于120字符。 较长的语句(>120字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要缩进三个Tab(以4空格/Tab计算),使排版整齐,语句可读。
perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN+STAT_SIZE_PER_FRAM*sizeof(_UL);act_task_table[frame_id*STAT_TASK_CHECK_NUMBER+index].occupied=stat_poi[index].occupied;report_or_not_flag=((taskno<MAX_ACT_TASK_NUMBER)&&(n7stat_stat_item_valid(stat_item))&&(act_task_table[taskno].result_data!=0));示例:2.1排版2.1.4一行程序不能大于120字符。示例:142.1排版2.1.5循环、判断等语句中若有较长的表达式或语句,则要进行适当的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。
示例:
if((taskno<max_act_task_number)&&(n7stat_stat_item_valid(stat_item))){}for(i=0,j=0;(i<BufferKeyword[word_index].word_length)&&(j<NewKeyword.word_length);i++,j++){}for(i=0,j=0;(i<first_word_length)&&(j<second_word_length);i++,j++){}2.1排版2.1.5循环、判断等语句中若有较长的表达式或152.1排版2.1.6若函数或过程中的参数较长,则要进行适当的划分。n7stat_str_compare((BYTE*)&stat_object,(BYTE*)&(act_task_table[taskno].stat_object),sizeof(_STAT_OBJECT));n7stat_flash_act_duration(stat_item,frame_id*STAT_TASK_CHECK_NUMBER+index,stat_object);示例:2.1排版2.1.6若函数或过程中的参数较长,则要进行适162.1排版2.1.7不允许把多个短语句写在一行中,即一行只写一条语句。rect.length=0;rect.width=0;错误示例:正确示例:rect.length=0;
rect.width=0;
2.1排版2.1.7不允许把多个短语句写在一行中,即一行172.1排版2.1.8
if、for、do、while、case、switch、default、return等语句自占一行,且if、for、do、while、switch等语句的执行语句部分无论多少都要加括号{}。if(pUserCR==NULL)return;
错误示例:正确示例:if(pUserCR==NULL)
{
return;
}
2.1排版2.1.8if、for、do、while、c182.1排版2.1.9防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错
。high<<8|low(1)a|b&&a&c(2)a|b<c&d(3)错误示例:正确示例:word=(high<<8)|low(1)
if((a|b)&&(a&c))(2)
if((a|b)<(c&d))(3)
由于:high<<8|low=(high<<8)|lowa|b&&a&c=(a|b)&&(a&c)
所以(1)(2)虽然表意不清,但不会出错由于:a|b<c&d=a|(b<c)&d
,所以(3)造成判断条件出错2.1排版2.1.9防止阅读程序时产生误解,防止因默认的192.1排版2.1.10程序块要采用缩进风格编写,缩进的空格数为4个。
说明:对于由开发工具自动生成的代码可以有不一致2.1.11函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。2.1.12对齐只使用空格键,不使用TAB键,除非编辑器有TAB转空格的功能。
说明:以免用不同的编辑器阅读程序时,因TAB键所设置的空格数目不同而造成程序布局不整齐。2.1排版2.1.10程序块要采用缩进风格编写,缩进的空202.1.13程序块的分界符(如大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。
在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。错误示例:正确示例:for(...){
...//programcode
}
if(...)
{
...//programcode
}
voidexample_fun(void)
{
...//programcode
}for(...){
...//programcode
}
if(...)
{
...//programcode
}
voidexample_fun(void)
{
...//programcode
}2.1.13程序块的分界符(如大括号‘{’和‘}’)应各独212.2注释安排注释程序的注释夹在程序中的注释是程序员与日后的程序读者之间通信的重要手段。注释决不是可有可无的。一些正规的程序文本中,注释行的数量占到整个源程序的1/3,甚至更多。注释分为序言性注释和功能性注释。2.2注释安排注释222.2注释序言性注释置于每个程序模块的开头部分,它应当给出程序的整体说明,对于理解程序本身具有引导作用。发布了模板的要求程序编制者按照模板逐项列出。2.2注释序言性注释232.2注释程序标题;有关本模块功能和目的的说明;主要算法;接口说明;有关数据描述:重要的变量及其用途,约束或限制条件,以及其它有关信息;模块位置:在哪一个源文件中,或隶属于哪一个软件包;修改日志。2.2注释程序标题;242.2注释功能性注释功能性注释嵌在源程序体中,用以描述其后的语句或程序段是在做什么工作,或是执行了下面的语句会怎么样。而不要解释下面怎么做。例如,
/*ADDAMOUNTTOTOTAL*/
TOTAL=AMOUNT+TOTAL
不好。
2.2注释功能性注释252.2注释如果注明把月销售额计入年度总额,便使读者理解了下面语句的意图:
/*ADDMONTHLY-SALESTOANNUAL-TOTAL*/
TOTAL=AMOUNT+TOTAL要点描述一段程序,而不是每一个语句;注释要正确。2.2注释如果注明把月销售额计入年度总额,便使读者理解了下262.2注释
2.2.1源代码只采用/*…*/注释风格,不采用//。2.2.2序言性注释符合Doxygen语法,并使用中文注释。2.2.3字符序列/*不能在注释中使用。
说明:C语言不支持注释的嵌套即使一些编译器支持这个语言扩展。
2.2注释2.2.1源代码只采用/*…*/注释27源文件布局:头文件布局:Fileheading 文件头
Revisionhistory版本信息
#include包含文件
#defineconstants常量定义
GlobalMacro 全局宏定义
Globaldatatypes全局数据类型定义
Localdatatype局部数据类型定义
Globalvariables全局变量
Globalfunctionprototypes全局函数原型Fileheading 文件头
Revisionhistory版本信息
\defgroup模块定义
#include包含文件
#defineconstants常量定义
Macros 宏定义
Globalvariables全局变量
Localvariables 局部变量
Localtables 局部表单
Localfunctionsprototypes
局部函数原型
Globalfunctions全局函数
Localfunctions 局部函数源文件布局:头文件布局:Fileheading 282.2注释2.2.5文件文件头模板。
必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等。修改日志以提交日期为准。
/**********************************************************这里填写项目名*Module:这里填写模块名*Copyright(c)2010-2015South-starLtd.Co.*AllRightsReserved.**History:*<author><time><version><desc>*rcmai2008-02-0115:001.0buildthisfile**********************************************************/示例:2.2注释2.2.5文件文件头模板。示例:292.2注释2.2.7函数头部应进行注释,供外部模块调用的h文件中的函数声明需要对函数功能进行注释。列出:函数的目的/功能、输入参数、输出参数、返回值、等。注意:在函数过程中发生改变的全局变量和输入参数需要在输出参数中说明。
示例请见下页
2.2注释2.2.7函数头部应进行注释,供外部模块调用的302.2注释/******************************************************************************//*!*\parDescription:* descriptionthefunctioninhere*\param[in]apara1*\param[in]bpara2*\param[in]cpara3*\param[out]none*\returntheresult*\retval0sucess*\retval1failed*******************************************************************************/intfunction(inta,intb,intc){}2.2注释/***********************312.2注释2.2.8边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。2.2.9对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下方,如放于上方则需与其上面的代码用空行隔开。2.2注释2.2.8边写代码边注释,修改代码同时修改相应322.2注释2.2.10对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。/*activestatistictasknumber*/#defineMAX_ACT_TASK_NUMBER1000#defineMAX_ACT_TASK_NUMBER1000/*activestatistictasknumber*/示例:2.2注释2.2.10对于所有有物理含义的变量、常量,如332.2注释2.2.11数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。
2.2.12
全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。2.2注释2.2.11数据结构声明(包括数组、结构、类342.2注释2.2.13
注释与所描述内容进行同样的缩排。
说明:可使程序排版整齐,并方便注释的阅读与理解。
voidexample_fun(void){/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlockTwo}voidexample_fun(void){/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlockTwo}错误示例:正确示例:2.2注释2.2.13注释与所描述内容进行同样的缩排。v352.2注释2.2.14
将注释与其上面的代码用空行隔开。
说明:可使程序排版整齐,避免代码显得过于紧凑。
/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo错误示例:正确示例:2.2注释2.2.14将注释与其上面的代码用空行隔开。362.2注释2.2.15
在程序块的结束行右方加注释标记,以表明某程序块的结束。
说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。
if(...){//programcodewhile(index<MAX_INDEX){//programcode}/*endofwhile(index<MAX_INDEX)*///指明该条while语句结束}/*endofif(...)*///指明是哪条if语句结束
示例:2.2注释2.2.15在程序块的结束行右方加注释标记,以372.2注释2.2.16
一行中如果有空语句,那么该行只能有这条空语句,不能有别的语句,并且在这条空语句前不能有注释,注释必须在其后,用空格隔开。
说明:可使程序排版整齐,避免代码显得过于紧凑。
while(port&0x80==0){;foo();①本行的错误是除了空语句还有一条语句;
/*waitforpin*/;②本行的错误是在空语句前有注释;
;/*waitforpin*/③本行的错误是空语句与注释没用空格隔开。}错误示例:2.2注释2.2.16一行中如果有空语句,那么该行只能有382.3标识符标识符的命名包括模块名、变量名、常量名、标号名、子程序名、数据区名以及缓冲区名等。这些名字应能反映它所代表的实际东西,应有一定实际意义。名字不是越长越好,应当选择精炼的意义明确的名字。
2.3标识符标识符的命名392.3标识符2.3.1标识符的有效字符不能多于31个。
说明:在大多数C语言的编译器和连接器中,只有变量或函数名的前31个字符的唯一性会被检查。2.3.2在内部范围的标识符不能和外部的标识符用同样的名字,因为会隐藏外部那个标识符。
Int16_t
i;Void
f(){int16_t
i;//此i不是彼ii=3;}不符合规范示例:2.3标识符2.3.1标识符的有效字符不能多于31个。402.3标识符2.3.3变量和函数名,文件名命名用小写字母开头的单词组合而成。宏,枚举值全部大写,单词间以’_’隔开。
示例:http_server_logs.h/*文件名*/enumurl_table_errors/*枚举名称为类型,规则与结构体名称相同*/{OK=0,/*枚举值采用全大写的方式*/ERROR_OUT_OF_MEMORY,ERROR_MALFORMED_INPUT,};voiddraw_box(void);//函数2.3标识符2.3.3变量和函数名,文件名命名用小写字412.3标识符2.3.4对于变量命名,禁止取单个字符(如i、j、k...),但i、j、k作局部循环变量是允许的。说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。2.3标识符2.3.4对于变量命名,禁止取单个字符(如i422.3标识符2.3.5标识符的命名要清晰、明了,有明确含义,建议使用完整的单词,若使用特殊约定或缩写,则要有注释说明。使用完整单词
intnum_errors;//Good.intnum_completed_connections;//Good.缩写:除非放到项目外也非常明了,否则不要使用缩写,例如:intnum_dns_connections;//Mostpeopleknowwhat"DNS"standsfor.不好的缩写intn_comp_conns;//Bad-ambiguousabbreviation.2.3标识符2.3.5标识符的命名要清晰、明了,有明确含432.3标识符2.3.6全局变量必须加g_前缀。intg_xmodle_ywidth其变量名解释如下:g全局变量Globalxmodle模块名称width变量含义示例:2.3标识符2.3.6全局变量必须加g_前缀。intg442.3标识符2.3.7用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。add/remove begin/end create/destroyinsert/delete first/last get/releaseincrement/decrementput/getadd/delete lock/unlock open/closemin/max old/new start/stopnext/previous source/target show/hidesend/receive source/destinationcut/paste up/downintmin_sum;intmax_sum;intadd_user(BYTE*user_name);intdelete_user(BYTE*user_name);示例:2.3标识符示例:452.3标识符2.3.8标识符不能重复使用。一个变量在存续期间只能用作一个用途,不能为了节省变量而被重复使用。示例:intfile_sector_num;/*变量定义用于文件扇区计数*/……file_sector_num=file_size/SECTOR_SIZE;……/*此处之后不再需要使用文件扇区数目*/file_sector_num=file_size;/*错误,变量被重复使用*/2.3标识符2.3.8标识符不能重复使用。462.3标识符2.3.9程序中不要出现仅靠大小写区分的相似的标识符。示例:intx,X;#defineSECTOR_SIZE512intsector_size;voidfoo(intx);voidFOO(floatx);2.3标识符2.3.9程序中不要出现仅靠大小写区分的相似472.3标识符2.3.10在提供给其它模块使用(在共享头文件件中定义的)的变量、结构、函数、宏及常量,以模块名加下划线开始。
示例:
宏定义:#defineRADIO_GET_INFO0X2//获取当前radio的一些状态信息枚举定义:typedefenum{GUI_LAYER_FORMAT_RGB565=0,GUI_LAYER_FORMAT_RGB565A,GUI_LAYER_FORMAT_RGB565CA,}gui_layer_format_t;
函数定义:intgui_dc_get(unsignedshorthwin);2.3标识符2.3.10在提供给其它模块使用(在共享头文482.3标识符2.3.11头文件必须加上头文件卫士,头文件卫士格式为:文件名中的“.”替换成“_”,然后在文件名前后各加上两个“_”。 除了编译开关/头文件等特殊应用,普通宏定义应避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。示例如下:头文件名:fs.h头文件卫士:#ifndef__FS_H__//双下划线#define__FS_H__……#endif2.3标识符2.3.11头文件必须加上头文件卫士,头文件492.4变量和数据类型2.4.1严禁使用未经初始化的变量作为赋值。说明:特别是在C/C++中引用未经赋值的指针,经常会引起系统崩溃。
2.4.2留心具体语言及编译器处理不同数据类型的原则及有关细节。说明:如在C语言中,局部变量将在“堆栈”中生成,而static局部变量将在内存“数据区”中生成。这些细节对程序质量的保证非常重要。
2.4变量和数据类型2.4.1严禁使用未经初始化的变量作502.4变量和数据类型2.4.3用typedef显式标识出各数据类型的长度和符号特性,避免直接使用标准数据类型,以提高代码可读性。注意其命名方式在同一产品中的统一。
说明:使用自定义类型,可以弥补编程语言提供类型少、信息量不足的缺点,并能使程序清晰、简洁。
可参考如下方式声明自定义数据类型。typedef
char
char_t;typedef
signed
int
int32_t;typedef
unsigned
short
uint16_t;typedef
unsigned
int
uint32_t;typedefunsignedlonguint64_t;示例:2.4变量和数据类型2.4.3用typedef显式标识出各512.5声明和定义2.5.1函数必须声明原型,在函数定义和调用时原型必须可见。说明:在原型声明中,函数的参数要在声明时指定参数名和类型具体的方法是:每一个外部函数都在头文件中有一个唯一的原型声明,需要调用此外部函数的源文件要包含此头文件,保证调用时由原型控制(原型对于“调用”可见);同时,函数定义所在的源文件也包含这一头文件,以便编译器可以检查原型声明和其定义相匹配(原型对于“定义”可见)。可参考如下页示例对函数进行声明、定义和调用。2.5声明和定义2.5.1函数必须声明原型,在函数定义和522.5声明和定义2.5.2无论何时对一个对象和函数声明或者定义,它的类型应该明确声明。2.5.3头文件中不允许包含对象或者函数的定义。说明:明确一个概念:所有可执行的代码或者对象和函数的定义都应在.C的源文件中,头文件中只能存在其声明。
具体的方法是:为全局变量和函数的声明增加extern修饰符,并在相应的.C源文件中定义变量或函数。2.5.4每个函数声明中的参数的类型应该和定义中的类型一致。
2.5声明和定义2.5.2无论何时对一个对象和函数声明或532.5声明和定义2.5.5在文件范围内声明和定义的所有对象或函数应该具有内部链接,除非是在需要外部链接的情况下。说明:如果一个变量或函数只是被同一文件中的函数所使用,那么就用static。使用static存储类标识符(或include了包含static变量或函数的头文件)将确保标识符只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性。注意:对于内联函数(inline),一般是在头文件中定义,并加上static,因为其目的就是为了在每一个调用函数里准备一份相同拷贝。
2.5声明和定义2.5.5在文件范围内声明和定义的所有对542.5声明和定义2.5.6声明必须出现在复合语句以前。
说明:在一个程序块中,局部变量的定义应该放在复杂表达式的前面。除非加上花括号,但作用域发生变化。{inti=0;...i=1;floatf;...}{floatf;inti=0;...i=1;...}
错误示例:正确示例:{inti=0;...i=1;{floatf;...}}
2.5声明和定义2.5.6声明必须出现在复合语句以前。{552.5声明和定义2.5.7
数组声明为外部时,应该明确声明大小或者直接初始化确定。
下面的数组声明是不规范的:
extern
int
array2[
];2.5.8数组和结构体的初始化不应少于其声明的大小。
下面的数组声明是不规范的:
intwrong[2][3]={{1,2,3}};
示例:示例:2.5声明和定义2.5.7数组声明为外部时,应该明确声明562.5声明和定义2.5.9地址操作符‘&’不能应用到一个定义为register‘的变量。因为对register变量取地址无效。
下面的数组声明是不规范的:例1:staticvoidfoo(void){registerinta;int*pa;pa=&a;/*不符合规范*/}例2:registerintarray[10];int*ptr=array;/*不符合规范*//*注:对于数组来说,&符可隐藏,&array等同于array*/
示例:2.5声明和定义2.5.9地址操作符‘&’不能应用到572.6函数2.6.1在定义不带参数的函数时应该使用“void”。intfoo(void);{...}2.6.2标记符的类型定义不应放在函数声明或函数定义的参数列表中。
说明:在C++中,函数声明或函数定义的参数列表中包含标记符的类型定义是非法的,虽然这在C语言中是合法的,但应尽量避免。下面的例子不符合规范:
intfoo(enumen{A,B,C}x);
示例:示例:2.6函数2.6.1在定义不带参数的函数时应该使用“voi582.6函数2.6.3函数标识符之后应该有“()”。
说明:在函数的调用中,如果函数名后面不加“()”,表示函数的指针,而不是函数的调用。下面的例子可能与作者的本意有冲突。
intfoo(void);intmain(void){...foo;/*函数名后面没有“()”*/...if(foo)/*函数名后面没有“()”*/{...}}示例:2.6函数2.6.3函数标识符之后应该有“()”。示例:592.6函数2.6.4在调用函数时,函数参数的类型或数量应该与函数原型、函数定义和之前的函数调用匹配。
下面的例子不符合规范。
例1:{intr;inta;r=foo(a);/*参数类型与函数原型中的冲突*/}externintfoo(longa);/*函数原型声明*/例2请见下页示例:2.6函数2.6.4在调用函数时,函数参数的类型或数量应602.6函数2.6.5尽量不要使用函数的递归调用
说明:递归调用特别是函数间的递归调用(如A->B->C->A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。
2.6函数2.6.5尽量不要使用函数的递归调用612.6函数2.6.6参数原型中的指针参数如果不是用于修改所指向的对象就应该声明为指向const的指针。
说明:本规则会产生更精确的函数接口定义。const限定可以保护对象本身。
下面的例子不符合规范。
voidmyfunc(int16_t*param1,constint16_t*param2,constint16_t*param3){*param1=*param2+*param3;return;}
在这个例子中,“param1”由于要被修改,所有不应该声明为const,“param2”和“param3”由于不被修改,所以都应该声明为const。示例:2.6函数2.6.6参数原型中的指针参数如果不是用于修改622.6函数2.6.7non-void类型函数的所有出口路径都应该有一个明确的return语句表达式,而不应该只有“return;”。
说明:如果定义了函数的返回类型为“非-void”,“return;”语句会导致函数的返回类型为“void”。
下面的例子不符合规范:intfunc(void){…return;/*没有明确的return语句表达式*/}
示例:2.6函数2.6.7non-void类型函数的所有出口路632.7控制流和表达式2.7.1循环体中和switchcase块中最多只能出现一个break语句用于结束循环。
说明:当循环体和case块中出现一个以上的break语句时,会使程序结构变的危险。
下面的例子不符合规范:
switch(n){case1:if(flag==0)break;/*不符合规范*/...break;case2:...示例:2.7控制流和表达式2.7.1循环体中和switchc642.7控制流和表达式2.7.2For循环不应该只执行一次。
说明:如果For循环只执行一次,则显得冗余。
下面的例子不符合规范:
intj;for(j=10;j<=10;j++){...}示例:2.7控制流和表达式2.7.2For循环不应该只执行一652.7控制流和表达式2.7.3if...elseif结构必须由一个else子句结束(如果只有一个if语句时,else不是必须的)。
说明:最后的else子句会包括其它所有没有在前面的子句中包括的情况,这样做能够提高程序的安全性和可靠性。
下面的例子不符合规范:
if(...){...}elseif(...)/*后面没有else子句*/{...}…示例:2.7控制流和表达式2.7.3if...els662.7控制流和表达式2.7.4表达式的值必须在任何求值顺序下保持一致。
说明:防止同一个表达式在不同的编译器中得到的结果不一样。下面的例子不符合规范:
例1:X=b[i]
+
i++;/*不同的编译器给出的结果不一样,
b[i]不一定先执行*/
例2:x=2;y=3;x=y*x++;/*求值顺序无法确定*/例3:if(a[++index]==a[index])
示例:2.7控制流和表达式2.7.4表达式的值必须在任何求值顺672.7控制流和表达式2.7.5逻辑运算符‘&&’或者‘||’右边不能包含单边作用。
说明:如果‘&&’的左边已经为‘0’或者‘||’的左边已经为‘1’,则右边不会执行。
下面的例子不符合规范:If(ishight)
&&
(x==
i++))/*如果ishight=0,那么i++不会执行*/示例:2.7控制流和表达式2.7.5逻辑运算符‘&&’或者‘|682.7控制流和表达式2.7.6逻辑运算符(&&、||和!)的操作数必须为一个有效的布尔值,布尔值表达式不允许进行逻辑运算以外的操作。
说明:这是为了防止误用。
inttrue=!0;/*符合规范*/intfalse=!1;/*符合规范*/intfalse=!2;/*不符合规范*/示例:2.7控制流和表达式2.7.6逻辑运算符(&&、||和692.7控制流和表达式2.7.7无格式的字符型不能与负数常量和零比较。
说明:无格式的字符型指既没有定义为unsigned也没有定义为signed的char类型。不同的编译器对其处理是不一样的,有的定义其可正可负,有的定义其只能为正。
下面的例子不符合规范:
voidf(charc1){if(c1<-3)/*和负数常量比较*/
c1++;if(c1<0)/*和零比较*/
c1++;}示例:2.7控制流和表达式2.7.7无格式的字符型不能与负数常702.7控制流和表达式2.7.8赋值运算符的左操作数不能进行转换操作,并且必须是一个可更改的对象。
下面的例子不符合规范:
intc=0;floatff=20.0F;floatgg=5.0F;constfloatf1=0.0F;/*不符合规范*/(char)c=ff*gg;/*不符合规范*/示例:2.7控制流和表达式示例:712.7控制流和表达式2.7.9无符号值不能与负数常量比较。
说明:无符号值与负数常量比较,可能会得到错误的结果。
下面的例子不符合规范:
intfoo(unsignedcharuca,unsignedshortusa,unsignedintuia){if(uca<NEG){…}if(usa<NEG){…}if(uia<NEG){…}}
示例:2.7控制流和表达式2.7.9无符号值不能与负数常量比722.8控制语句表达式2.8.1赋值语句不能用在一个产生布尔值的表达式中。下面的例子不符合规范:例1:If((x=y)!=0)例2:If
(x=y)2.8.2判断一个值是否为0,应该是显式的,除非该操作数是一个布尔值。
下面的例子不符合规范:
uint8_tx;…if(x){…}示例:示例:2.8控制语句表达式2.8.1赋值语句不能用在一个产生布732.8控制语句表达式2.8.3不允许对浮点数进行相等或者不相等的比较,即使是非直接的比较也是不允许的。下面的例子不符合规范:float32_tx,y;...if(x<=y){...}2.8.4For循环的控制语句表达式中不能包含任何浮点类型。
说明:For循环中的索引应该为整型数。
示例:2.8控制语句表达式2.8.3不允许对浮点数进行相等或者742.8控制语句表达式2.8.5For循环控制语句中的3个表达式只能和循环控制相关。第一个表达式只能为循环变量赋初值,第二个表达式只能进行循环条件的判断,第三个表达式只能进行循环变量增(减)值。
说明:这样可以增强程序的可理解性。
下面的例子不符合规范:
for(i==0;i<10;i++){}
示例:2.8控制语句表达式2.8.5For循环控制语句中的3752.8控制语句表达式2.8.6For循环中,循环变量只能在For循环控制语句的第三个表达式中修改,不允许在循环体中修改。
说明:这样可以使循环保持清晰,增强程序的可理解性。
下面的例子不符合规范:
Flag=1;For(i=0;(i<5)&&(flag==1);i++){Flag=0;i=i+3;}示例:2.8控制语句表达式2.8.6For循环中,循环变量只762.8控制语句表达式2.8.7布尔表达式的值必须是可以改变的。下面的例子不符合规范:
例1:uint8_tx;…if(x>=0)/*错误在于该条件判断的结果始终为真*/…例2:loop=5;...while(loop){...}示例:2.8控制语句表达式2.8.7布尔表达式的值必须是可以改772.9数据冗余2.9.1不能存在执行不到的代码。
下面的例子不符合规范:
Swich(event){Case
www;
do_wakeup();
break;
do_more();/*这条语句执行不到*/…}示例:2.9数据冗余2.9.1不能存在执行不到的代码。示例:782.9数据冗余2.9.2非空语句必须要么产生单边作用(side-effect);或者使程序流程改变。
下面的例子不符合规范:
…x>=3;i;…
2.9.2没有使用到的标识符和标记应该删除。2.9.3','的左操作数应该有单边作用。
下面的例子不符合规范:
for(i,j=strlen(s)-1;i<j;i++,j--)示例:2.9数据冗余2.9.2非空语句必须要么产生单边作用(s792.10程序效率2.10.1循环体内工作量最小化。
说明:应仔细考虑循环体内的语句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的时间效率。
如下代码效率不高:
for(ind=0;ind<MAX_ADD_NUMBER;ind++){sum+=ind;back_sum=sum;/*backupsum*/}
语句“back_sum=sum;”完全可以放在for语句之后,如下:for(ind=0;ind<MAX_ADD_NUMBER;ind++){sum+=ind;}back_sum=sum;/*backupsum*/低效示例:高效示例:2.10程序效率2.10.1循环体内工作量最小化。低效示802.10程序效率2.10.2在多重循环中,应将最忙的循环放在最内层。
说明:减少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];}}低效示例:高效示例:2.10程序效率2.10.2在多重循环中,应将最忙的循环812.10程序效率2.10.3避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。
说明:目的是减少判断次数。循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。如下代码效率稍低:
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;}}/*高效示例请见下页*/低效示例:2.10程序效率2.10.3避免循环体内含判断语句,应将822.10程序效率
因为判断语句与循环变量无关,故可如下改进,以减少判断次数: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;}}
高效示例:2.10程序效率高效示例:832.11指针2.11.1指针不能转换为函数或者整型以外的其他类型。
说明:指针值是一个int型的整数,只能强制转换为函数或整形类型,而不能强制转换为指向其它类型。
floati;floatx;intpi;pi=(int)&i;/*符合规范*/x=(float)&i;/*不符合规范*/示例:2.11指针2.11.1指针不能转换为函数或者整型以外的842.11指针2.11.2指向不同数据类型的指针之间不能相互转换。
说明:因为不同的数据类型分配的字节空间可能不同,将指向多字节空间的指针转换为指向少字节空间的指针不会有问题,但反之就有可能出现错误。
下面的例子不符合规范:例1:voidfunction(char*string,int*number){int*pi;char*pc;
pc=(char*)number;/*Message310*/pi=(int*)string;/*Message310&3305*/}/*例2请见下页*/示例:2.11指针2.11.2指向不同数据类型的指针之间不能相852.11指针下面的例子不符合规范:
例2: char*pc;/*1bytealigned*/ int*pi;/*2bytealigned*/ long*pl;/*4bytealigned*/ pi=(int*)pc;/*指针转换到了更严格的序列*/ pc=(char*)pl;/*没有问题,但是不建议这样做*/示例:2.11指针示例:862.11指针2.11.3指针转换过程中不允许丢失指针的constvolatile属性。下面的例子不符合规范:intx;int*pi;/*指向整形的指针*/int*constpci1=&x;/*const指针*/constint*pci2;/*指向const整形的指针*/volatileint*pci3;/*指向volatile整形的指针*/
...pi=pci1;/*符合规范*/pi=(int*)pci2;/*不符合规范*/pi=(int*)pci3;/*不符合规范*/示例:2.11指针2.11.3指针转换过程中不允许丢失指针的c872.11指针2.11.4只有指向数组的指针才允许进行算术运算。
说明:此处的算术运算仅仅限定于指针加减某个整数,比如ppoint=point-5,ppoint++等。下面的例子不符合规范:int*px;inti;px=&i;px=px+2;++px;
下面的例子符合规范:
int*px;inta[10];px=a;px=px+2;++px;错误示例:正确示例:2.11指针2.11.4只有指向数组的指针才允许进行算术882.11指针2.11.5只有指向同一个数组的两个指针才允许相减。
说明:两个指针可指向同一数组的不同成员。
下面的例子不符合规范:inta[10];intb[10];intx,*p1,*p2;x=p1–p2;
示例:2.11指针2.11.5只有指向同一个数组的两个指针才允892.11指针2.11.6只有指向同一个数组的两个指针才允许用>,>=,<,<=等关系运算符进行比较。
说明:两个指针可指向同一数组的不同成员。
下面的例子不符合规范:chara[10];charb[10];intx;x=a<b;
下面的例子符合规范:chara[10];char*p1,*p2;intx;p1=a;p2=a+2;x=p1<p2;
错误示例:正确示例:2.11指针2.11.6只有指向同一个数组的两个指针才允902.11指针2.11.7指针的索引值不能为负。 下面的例子不符合规范:voidfoo(int*p,intn){intr;if(n<-5){
r=p[n];/*指针的索引值为负*/
...
r=*(p+n);/*指针的索引值为负*/}}
示例:2.11指针2.11.7指针的索引值不能为负。示例:912.11指针2.11.8不允许对指针值可能为NULL的指针进行算术运算。
说明:这样能保证程序的安全性和可靠性。
下面的例子不符合规范:externintbuf[10];voidfoo(intn){int*p=NULL;for(i=1;i<=n;++i){...p=&buf[i];...}++p;/*对指针值可能为NULL的指针进行算术运算*/}
示例:2.11指针2.11.8不允许对指针值可能为NULL的指922.11指针2.11.9动态分配对象的地址不允许在本对象消亡后传给另外一个对象。
说明:这条规范可以分为下面几种情况:(1)将动态分配的局部变量的地址赋值给一个带链接的或更宽范围的指针是危险的,一旦局部变量的内存空间被释放,这个指针会成为无效的指针。(见例1)下面的例子不符合规范:例1:externint*pi;voidf(void){inta;pi=&a;}/*例2、例3请见下页*/示例:2.11指针2.11.9动态分配对象的地址不允许在本对象932.11指针2.11.10一个未知大小的对象的指针不能成为加法或者减法操作的左操作数。
下面的例子不符合规范:typedefstructTAGT;staticintfoo(intn,void*pv){T*v1=0;v1=v1+n;/*不符合规范*/
pv=pv+n;/*不符合规范*/v1=v1-n;/*不符合规范*/
pv=pv-n;/*不符合规范*/}示例:2.11指针2.11.10一个未知大小的对象的指针不能成942.11指针2.11.11只有整数表达式能加到指针。
下面的例子不符合规范:int*ptr;floatdec;ptr=ptr+dec;
2.11指针2.11.11只有整数表达式能加到指针。952.12Switch语句2.12.1所有非空的Switchcase子句都应该以break语句结束。
switch(value){caseONE:++x;caseTWO:/*这里缺少一条break语句*//*...*/break;caseTHREE:/*空case语句,这里没有break语句是符合规范的*/default:break;}
示例:2.12Switch语句2.12.1所有非空的Switc962.12Switch语句2.12.2Switch的最后一个子句必须是default子句,如果default中没有包含任何语句,那么应该有注释来说明为什么没有进行任何操作。
说明:最后的default子句会包括其它所有没有在前面的子句中包括的情况,这样做能够提高程序的安全性和可靠性。
2.12Switch语句2.12.2Switch的最后972.12Switch语句2.12.3Switch控制表达式不能是一个常量。
说明:如果Switch的控制表达式是一个常量,可以用if语句等其它形式代替。下面的例子不符合规范:switch(x==0){...}示例:2.12Switch语句2.12.3Switch控制表982.12Switch语
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 茶叶店茶艺展示与品鉴会活动方案
- PFMA制程失效模式与效应分析考核试题(含详细答案)
- 花卉园艺试题及答案
- 冠脉旋磨术中血管痉挛全程防控共识
- 重症肌无力肺部感染早期识别宣教共识
- 2025-2026学年黑龙江省双鸭山市海林市初中历史八年级期末下册高分预测经典测试题详细参考解析
- 2026年文印员理论考试题及答案
- OGP岗位综合能力测试题(含详细答案解析)
- 慢性创面创面拭子与组织活检选择专家共识(2026版)
- 耐火材料安全师考试题库及答案解析
- 数学-湖南炎德英才2026年秋季高一上学期10月联考
- 直肠癌腹会阴联合切除范围课件
- 2026-2031年中国高端私人会所行业市场全景调研及发展趋势预测报告
- 第25课《陈涉世家 》课件(内嵌视频)2026-2027学年统编版语文九年级上册
- 中国共产党纪律处分条例题库附答案
- 深化岗区队建设实施方案
- 七一重要讲话精神学习纲要
- 【期末复习】2025-2026学年人教版物理九年级全一册知识点汇Z
- GB/T 47543-2026无障碍旅游服务规范旅游饭店
- GB/T 34395-2026展览场馆功能性设计指南
- 检察院保密培训
评论
0/150
提交评论