前 言
1 目的
2 适用范围
3 总体原则
4 程序的版式
4.1规则:程序块要采用缩进风格编写,缩进的空格数为4个。
4.2规则:缩进或者对齐只能使用空格键,不可使用TAB 键。
4.3规则:相对独立的程序块之间、变量说明之后必须加空行。
4.4规则:较长的语句(>80字符)要分成多行书写。
4.5规则:不允许把多个短语句写在一行中,即一行只写一条语句。
4.6 规则:if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
4.7规则:代码行之内应该留有适当的空格
4.8建议:程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。
5 注释
5.1规则:源文件头部应进行注释,列出:生成日期、作者、模块目的/功能等。
5.2规则:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值等。
5.3规则:注释应该和代码同时更新,不再有用的注释要删除。
5.4规则:注释的内容要清楚、明了,不能有二义性。
5.5建议:避免在注释中使用非常用的缩写或者术语。
5.6建议:注释的主要目的应该是解释为什么这么做,而不是正在做什么。如果从上下文不容易看出作者的目的,说明程序的可读性本身存在比较大的问题,应考虑对其重构。
5.7建议:避免非必要的注释。
5.8规则:注释的版式
5.9规则:对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。
5.10规则:数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释可放在此域的右方。
5.11建议:对重要变量的定义需编写注释,特别是全局变量,更应有较详细的注释,包括对其功能、取值范围、以及存取时注意事项等的说明。
5.12建议:分支语句(条件分支、循环语句等)需编写注释。
5.13规则:注释不宜过多,也不能太少,源程序中有效注释量控制在20%~30%之间。
6 标识符命名
6.1规则:命名尽量使用英文单词,力求简单清楚,避免使用引起误解的词汇和模糊的缩写,使人产生误解。
6.2规则:命名规范必须与所使用的系统风格保持一致,并在同一项目中统一。
6.3建议:变量的命名可参考“匈牙利”标记法(Hungarian Notation):TypePrefix+ Name
6.4规则:常量、宏和模板名采用全大写的方式, 每个单词间用下划线分隔。
6.5建议:枚举类型enum 常量应以大写字母开头或全部大写。
6.6建议:命名中若使用了特殊约定或缩写,则要有注释说明。
6.7规则:自己特有的命名风格,要自始至终保持一致,不可来回变化。
6.8规则:对于变量命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。
6.9建议:除非必要,不要用数字或较奇怪的字符来定义标识符。
6.9建议:函数名以大写字母开头,采用谓-宾结构(动-名),且应反映函数执行什么操作以及返回什么内容。
6.10建议:类、结构、联合、枚举的命名须分别以C、S、U、E开头,其他部分遵从一般变量命名规范。
7 可读性
7.1规则:用括号明确表达式的操作顺序,避免使用默认优先级。
7.2建议:不要编写太复杂 、多用途的复合表达式。
7.3规则:涉及物理状态或者含有物理意义的常量,避免直接使用数字,必须用有意义的枚举或常量来代替。
7.4规则:禁止使用难以理解,容易产生歧义的语句。
8 变量、结构
8.1建议:尽量少使用全局变量,尽量去掉没必要的公共变量。
8.2规则:变量,特别是指针变量,被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。
8.3建议:仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间,并减少引起误用现象。
8.4建议:留心具体语言及编译器处理不同数据类型的原则及有关细节。
8.5建议:尽量减少没有必要的数据类型默认转换与强制转换。
8.6规则:当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题。
9 函数、过程
9.1规则:调用函数要检查所有可能的返回情况, 不应该的返回情况要用ASSERT来确认。
9.2建议:编写可重入函数时,应注意局部变量的使用(如编写C/C++语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。
9.3建议:调用公共接口函数时,调用者有保障调用参数符合要求的义务。作为一种防御性的编程风格,被调用函数也应该对传入参数做必要的安全检查。
9.4建议:函数的规模尽量限制在100行以内。
9.5建议:一个函数仅完成一件功能。
9.6建议:不能用ASSERT代替必要的安全处理代码,确保发布版的程序也能够合理地处理异常情况。
9.7尽量写类的构造、拷贝构造、析构和赋值函数 ,而不使用系统缺省的。
9.8建议:对于不需要拷贝构造函数时,应显式地禁止它,避免编译器生成默认的拷贝构造函数。
9.9建议:谨慎使用与程序运行的环境相关的系统函数。
9.10建议:禁止编写依赖于其他函数内部实现的函数。
9.11规则:检查函数所有参数与非参数的有效性。
9.12建议:函数实现中不改变内容的参数要定义成const。
9.13规则:函数的返回值要清楚、明了,让使用者不容易忽视错误情况。
10 C++专用规范
10.1规则:在高警告级别下干净地编译。
10.2规则:确保资源为对象所占有,使用显式的RAII和智能指针。
10.3规则:主动使用const,避免使用宏。
10.4规则:合理使用组合(composition)和继承(inheritance)。
10.5规则:尽可能局部地声明变量。
10.6规则:通过值,(智能)指针,或引用适当地取得参数。
10.7规则:不要在头文件中定义具有链接属性的实体。
10.8规则:尽量用异常来报告错误。
11 附则
附录A
1规则:在保证软件系统的正确性、稳定性、可读性及可测性的前提下,提高代码效率。
2规则:局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响。
3建议:通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率。
4规则:循环体内工作量最小化
5建议:对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率。
6建议:避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。
7建议:在逻辑清楚且不影响可读性的情况下,代码越少越好。
8规则:尽量使用标准库函数,不要“发明”已经存在的库函数。
9建议:要尽量重用已有的代码,直接调用已有的API 。
附录B
1规则:只引用属于自己的存贮空间。
2规则:防止引用已经释放的内存空间。
3规则:过程/函数中动态分配的资源(包括内存、文件等),在过程/函数退出之前要释放。
4建议:充分理解new/delete,malloc/free 等指针相关的函数的意义,对指针操作时需小心翼翼。
5规则:防止内存操作越界。
6建议:要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。
7建议:条件表达式要把常量写在前面。
8建议:有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。
9规则:尽量少用goto语句。
10规则:不使用与硬件、操作系统、或编译器相关的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性。
11建议:时刻注意表达式是否会上溢、下溢。
12规则:使用第三方提供的软件开发工具包或控件时,要注意以下几点:
13规则:资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL文件或其它单独的描述文件(如数据库格式)。
14规则:打开编译器的所有告警开关对程序进行编译,并且要确认、处理所有的编译告警。
15建议:通过代码走读及审查方式对代码进行检查。
16建议:如果可能,单元测试要覆盖98%以上的代码,尽可能早地发现和解决问题。
17建议:如果可能,尽量使用pc-lint,purify,LogiScope 等测试工具,以提高效率。
附录C