C编码规范规范综述.docx
- 文档编号:23812593
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:19
- 大小:25.04KB
C编码规范规范综述.docx
《C编码规范规范综述.docx》由会员分享,可在线阅读,更多相关《C编码规范规范综述.docx(19页珍藏版)》请在冰豆网上搜索。
C编码规范规范综述
C/C++编码规范
广州从兴电子开发有限公司
GUANGZHOUSUNRISEELECTRONICSDEVELOPMENTCO.,LTD
1引言
为了提高源程序的质量和可维护性,最终提高公司软件产品生产力,我们有必要对公司软件产品的源程序的编写风格作出统一的规范约束。
本规范总则的内容包括:
排版、注释、标识符命名、变量使用、代码可测性、程序效率、质量保证等。
本规范采用以下的术语描述:
★规则:
编程时强制必须遵守的原则。
★说明:
对此规则或建议进行必要的解释。
★示例:
对此规则或建议从正、反两个方面给出例子。
2排版
2-1程序块要采用缩进风格编写,缩进允许4个空白字符或者一个TAB键,同一个模块的风格必须一致。
(建议)
建议使用4个空白字符,如使用TAB键,则应该在环境中也设置为4个空白。
2-2函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。
(建议)
2-3注释与所描述内容进行同样的缩排。
(建议)
说明:
可使程序排版整齐,并方便注释的阅读与理解。
错误示例:
voidexample_fun()
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
应改为如下布局。
voidexample_fun()
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
2-4相对独立的程序块之间、变量说明之后必须加空行。
(建议)
错误示例:
if(!
valid_ni(ni))
{
//programcode
}
repssn_ind=ssn_data[index].repssn_index;
repssn_ni=ssn_data[index].ni;
正确示例:
if(!
valid_ni(ni))
{
//programcode
}
repssn_ind=ssn_data[index].repssn_index;
repssn_ni=ssn_data[index].ni;
2-5较长的语句要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读,下一行至少有一个缩进。
(建议)
正确示例:
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;
act_task_table[taskno].duration_true_or_false
=SYS_get_sccp_statistic_state(stat_item);
report_or_not_flag=((taskno &&(n7stat_stat_item_valid(stat_item)) &&(act_task_table[taskno].result_data! =0)); 2-6若函数或过程中的参数较长,则要进行适当的划分,按逗号分行。 (强制) 正确示例: n7stat_str_compare((BYTE*)&stat_object, (BYTE*)&(act_task_table[taskno].stat_object), sizeof(_STAT_OBJECT)); 2-7不允许把多个短语句写在一行中,即一行只写一条语句。 (强制) 错误示例: rect.length=0;rect.width=0; 正确示例: rect.length=0; rect.width=0; 2-8程序块的分界符(如C/C++语言的大括号‘{’和‘}’),允许有两种方式,独占一行并且位于同一列,同时与引用它们的语句左对齐;或者放在行的结尾。 在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。 (强制) 正确示例: for(...) { //programcode }//~endfor(...) 正确示例: for(...){ ...//programcode } 2-9在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。 (建议) 说明: 采用这种松散方式编写代码的目的是使代码更加清晰。 由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C++语言中括号已经是最清晰的标志了。 在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。 给操作符留空格时不要连续留两个以上空格。 正确示例: (1)逗号、分号只在后面加空格。 inta,b,c; (2)比较操作符,赋值操作符"="、"+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"<<"、"^"等双目操作符的前后加空格。 if(current_time>=MAX_TIME_VALUE) a=b+c; a*=2; a=b^2; (3)"! "、"~"、"++"、"--"、"&"(地址运算符)等单目操作符前后不加空格。 *p='a';//内容操作"*"与内容之间 flag=! isEmpty;//非操作"! "与内容之间 p=&mem;//地址操作"&"与内容之间 i++;//"++","--"与内容之间 (4)"->"、"."前后不加空格。 p->id=pid;//"->"指针前后不加空格 (5)if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。 if(a>=b&&c>d) 3注释 3-1说明性文件(如头文件.h文件、.inc文件、.def文件、配置说明文件.cfg等)头部应进行注释,注释必须列出: 版权说明、作者和功能简要说明。 (强制) /* *@(#)Blah.java1.8299/03/18 * *Copyright(C)1995,1996,1997,and1998WIDEProject. * *FIPSpub180-1: SecureHashAlgorithm(SHA-1) *basedon: http: //csrc.nist.gov/fips/fip180-1.txt *implementedbyJun-ichiroitojunItoh * *@version1.8218Mar1999 *@authorFirstnameLastname * */ 3-2函数头部应进行注释,列出: 函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。 (强制) /** *Description: checkout提款 *@paramHashtablecartinfo *@paramOrderBeanorderinfo *@returnresult *@exception */ intcheckout(Hashtable*htCart,OrderBean*orderBean) 3-3不再有用的注释要删除,以保证注释与代码的一致性。 (强制) 3-4避免在注释中使用缩写,特别是非常用缩写。 (建议) 说明: 在使用缩写时或之前,应对缩写进行必要的说明。 3-5注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。 (建议) 错误示例: 例1: /*Internationalroamercalculatetollfee*/ strcpy(deb.chargecode,CHARGE_IDD); strcpy(deb.calltype,CALLTYPE_IDD); 例2: strcpy(deb.chargecode,CHARGE_IDD); strcpy(deb.calltype,CALLTYPE_IDD); /*Internationalroamercalculatetollfee*/ 正确示例: /*Internationalroamercalculatetollfee*/ strcpy(deb.chargecode,CHARGE_IDD); strcpy(deb.calltype,CALLTYPE_IDD); 3-6对于所有有特定含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其特定含义。 变量、常量、宏的注释应放在其上方相邻位置或右方。 (建议) 正确示例: /*activestatistictasknumber*/ #defineMAX_ACT_TASK_NUMBER1000 #defineMAX_ACT_TASK_NUMBER1000/*activestatistictasknumber*/ 3-7数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。 对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。 (强制) 正确示例: /*structuredefinitionforparameterrequestitem*/ typedefstruct{ char*name;/*parametername*/ inttype;/*datatype*/ void*value;/*variabletostoreparametervalue*/ intneed;/*needful*/ intsize;/*variablesize*/ int*number;/*variabletostoreparametercount*/ intnummax;/*arrarysize*/ }Para,*pPara; 3-8在程序块的结束行右方加注释标记,以表明某程序块的结束。 (建议) 说明: 当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。 正确示例: if(...) { //programcode while(index { //programcode }//~endwhile(index }//~endif(...) 3-9命名中若使用特殊约定或缩写,则要有注释说明。 (强制) 说明: 应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。 3-10无用的代码不能注释掉。 (强制) 要么删除,要么使用条件编译屏蔽。 可以这样写: #ifdef0 /*无用的代码*/ #endif 4命名规则 4-1常量名称统一使用大写,标识符必须指示常量具体含义。 (强制) #defineMAX_PATH256 4-2变量名称禁止取单个字符(如i、j、k...),标识符必须指示常量具体含义,但是i、j、k作局部循环变量是允许的。 (强制) 4-3类的方法的命名和过程、函数的命名一样。 类的属性名应为名词。 属性的命名规则和其他的变量相同。 (建议) 4-4设置输入参数值的例程名应当以set为其前缀,获取数值的例程名应当以get为其前缀。 (建议) 4-5标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。 (建议) 说明: 较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。 5可读性 5-1注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。 (强制) 说明: 防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。 正确示例: word=(high<<8)|low (1) if((a|b)&&(a&c)) (2) if((a|b)<(c&d))(3) 错误示例: high<<8|low a|b&&a&c a|b 由于 high<<8|low=(high<<8)|low, a|b&&a&c=(a|b)&&(a&c), (1) (2)不会出错,但语句不易理解; a|b 5-2源程序中关系较为紧密的代码应尽可能相邻。 (强制) 说明: 便于程序阅读和查找。 错误示例: rect.length=10; char_poi=str; rect.width=5; 正确示例: rect.length=10; rect.width=5;//矩形的长与宽关系较密切,放在一起。 char_poi=str; 5-3不要使用难懂的技巧性很高的语句,除非很有必要时。 (强制) 说明: 高技巧语句不等于高效率的程序,实际上程序的效率关键在于算法。 错误示例: *stat_poi+++=1; *++stat_poi+=1; 正确示例: *stat_poi+=1; stat_poi++;//此二语句功能相当于“*stat_poi+++=1;” ++stat_poi; *stat_poi+=1;//此二语句功能相当于“*++stat_poi+=1;” 6数据类型 5-1禁止数据类型隐性地从高精度向低精度转换(强制) 例如int转换为short型或者char型。 double型转换为float型。 7常量 7-1C或者C++文件中,除允许出现-1,0,1三个数字外,其他数字都必须以常量方式定义,同一类常量应该统一格式,当-1,0,1有非常具体的意义时,也应该以常量代替。 (强制) 所有有特殊意义的数字都应该使用使用常量代替。 魔幻数字有百害而无一利,应该完全杜绝使用,特殊情况下可以使用数字。 例如strncpy(dest,src,5); 数字0主要可能出现在循环起始、数据结构初始化等地方。 -1主要出现在与函数结果比较的地方。 1应该是可以不需要出现的,不过有的地方确实以1为下标的。 给数组连续赋值和从数组中连续读取值可以采用以下方法实现: intindex=0; a=array[index++]; b=array[index++]; c=array[index++]; 这种方式比以下方式: a=array[0]; b=array[1]; c=array[2]; 好一些,好处如下: (1)如果下标需要修改为从1开始,那么只需要修改index=1即可,而第二种方法需要逐个修改。 (2)程序更加整齐,眼睛瞟一下就能够发现异常情况,特别是在项数比较多的情况下,只需要检查左边即可,右边都是一样的。 第二种情况需要检查左右两边,容易出错。 (3)如果数据内容顺序做了修改,只需要挪动相应的程序行即可,第二种方法必须修改索引。 7-2避免直接使用字符串,大部分地方可以用常量代替,有些地方可以以整数代替(即字符串的索引)。 (建议) 当前公司的业务主要是处理数值,字符串主要用做提示和说明信息,对计算机来说,处理整数的效率比处理字符串的效率不止高2个数量级。 字符串中涉及到空白,大小写,编码等情况,容易出错。 例如需要显示无效的参数,不直接使用“invalidparam” 而是使用常数: #defineINVALID_PARAM“invalidparam” 或者定义数组: staticcharerrmsg[]={“invalidparam”}; #defineINVALID_PARAM0 使用字符串“20080102083445”表示时间,可以改为用time_t或者其他时间类或者结构来表示。 8变量、结构 8-1绝大部分情况下禁止使用系统级的全局变量,而文件级的静态只读的全局变量则是可以使用的,函数库中不能输出全局变量。 (强制) 全局变量在多线程应用中可能带来很多问题,推荐使用其他开发软件中的方法。 定义一个结构(在C++中可以定义一个这样的类) typedefstruct_context { /*需要用作全局变量内容放在这里*/ }CONTEXT; 系统中绝大部分函数都把这个参数(CONTEXT*ctx)作为第一个参数,这样就没有全局变量的必要了。 特殊情况的例子如下: 系统中的所有错误信息可以通过只读的全局变量集中存放,放在一个c/cpp文件中,以static标识。 例如: staticcharerrmsg[]={“error1”, “error2”}; 这种做法是无害的。 这种方式通常用来保存错误信息或者提示信息。 8-2结构的定义(强制) 结构的定义要求使用unix中的定义方式,全部以小写表示。 例如: structtimeval{ longtv_sec;/*secondssinceJan.1,1970*/ longtv_usec;/*/*andmicroseconds*/ }; 结构的定义方式为强制,结构中成员变量的定义方式建议使用结构名的缩写,加上下划线再加变量。 9类 9-1类名定义(建议) 类的名字必须由一个或数个能表达该类的意思的大写字母开头而其它字母都小写的单词或缩写组成。 这样能使这个类的名称能更容易被理解, 例如: classStudents { public: intgetName(char*buf,int*len); intsetName(char*buf,intlen); private: charname[MAX_NAME_LEN]; }; 9-2成员变量(强制) 变量名由一个或数个能表达该变量的意思的单词组成,使用大小写混合的方式,每一个词是小写,后面的词第一个字母大写,其它小写。 9-3成员函数(强制) 成员函数的名称应该是一个动词,使用大小写混合的方式,每一个词是小写,后面的词第一个字母大写,其它小写。 9-4禁止在C++类中使用非基本类型的静态成员变量。 (强制) 如果在类中使用其他类的实例作为静态变量,系统在连接和初始化时可能会出现问题,可以使用静态非基本类型的成员变量指针。 非基本类型的指针仍然是基本类型。 10宏 10-1宏定义(建议) 宏定义应该全部使用大写字母,用下划线隔开多个词汇,当宏中语句比较多时,推荐使用以下方法定义,例如: #definePERF_CHECK(x)do{if((x)==0)\ Xxxx;\ else\ Xxxx;\ }while(0) 即用do{}while(0),把语句包起来,linux的源代码中基本上都是这样做的,这是防止宏扩展时出问题的最好办法,而且不会增加运行时CPU的负担,因为do{}while(0)语句会被编译器优化掉。 11函数、过程 11-1函数的规模尽量限制在200行以内。 (建议) 说明: 不包括注释和空格行。 12错误代码 12-1错误代码的定义。 (强制) 应该用数值来表示错误代码,其格式应该一样,例如用ERR作为前缀,后面用动宾结构说明原因,同类的错误应该合并,例如: #defineERR_BASE1000 #defineERR_OPEN_FILE(ERR_BASE+1) #defineERR_CREATE_FILE(ERR_BASE+2) 错误内容可以通过一个函数,例如strerror返回。 公司将来可以收集所有的错误代码和文字信息,统一命名并应用到所有项目中。 13调试 13-1以DEBUG宏是否定义产生调试版本和发布版本。 (强制) DEBUG宏是一个总开关,可以在DEBUG宏的基础上定义其他宏。 如果DEBUG宏没有定义,那么其他宏都是没有定义的。 即使DEBUG宏定义了,可能还必须定义其他宏来调试不同的内容。 例如定义DEBUG_DB来表示调试数据库的相关内容。 13-2使用VERIFY宏。 (建议) #ifdefDEBUG #defineVERIFY(e)\ (! (e)? (void)0: \ (fprintf(stderr,"Verifyfailure: %s: %d: \"%s\"",\ __FILE__,__LINE__,#e),abort())) #else #defineVERIFY(e)(e) #endif 如果定义了DEBUG宏,这个宏有效。 否则直接执行表达式e。 这个宏当e的值为非0时,将打印错误行和内容,并且退出。 如果遵循了函数的返回规范,把这个宏加到函数上,可以保证对每个函数的返回值都进行检查。 14内存管理 14-1内存管理应该遵循谁申请谁释放、谁提供申请方法谁就提供释放方法的原则。 (建议) 如果一个类或者模块提供了一个函数,内部包含了申请内存的功能。 应该同时提供一个函数,允许释放这些内存。 而不应该让调用程序通过free或者delete来释放内存。 这样有如下好处: (1).该类或者模块内部可以改变内部申请和释放内存的方式,只需要申请和释放方式互相对应即可。 (2).外部调用程序不用关心类或者模块的内部实现,只需配对使用接口即可。 (3).出现内存泄漏时可以分别测试定位,降低了模块之间的藕合。 15实践建议 15-1应用中不直接使用C/C++语言中的数据类型 应用中不直接使用int、void*、char*类型除外的C/C++的数据类型。 int类型的使用主要用作索引、次数等,因为索引、次数都是从0开始,基本上不会使整数溢出。 不应该使用C++的bool类型,直接用整数代替,因为整数具有bool
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编码规范规范综述 编码 规范 综述