个人编码模板
前言
计算机程序设计是一项人类的活动,编写的程序是为了人们阅读、理解、使用甚至修改的。良好的程序设计风格是程序员成功的保障,也促进了技术的交流,有助于提高程序的可靠性、可理解性、可测试性、可维护性和可重用性,改善软件的质量。因此形成一个良好的程序设计风格对我们来说非常重要。经过查找各大公司的编程风格的要求,整理如下:
1 程序的版式
1.1 程序块要采用缩进的风格编写缩进的,缩进的空格数为四个。
1.2 缩进或者对齐只使用空格键,不使用Tab键。
1.3 相对独立的程序块之间、变量说明之后必须加空行。
说明:
以下情况应该是用空行分开:
1)函数之间应该用空行分开;
2)变量声明应尽可能靠近第一次使用处,避免一次性声明一组没有马上使用的变量;
3)用空行将代码按照逻辑片断划分;
4)每个类声明之后应该加入空格同其他代码分开。
例:
if (!valid_ni(ni))
{
... // program code
}
repssn_ind = ssn_data[index].repssn_index;
repssn_ni = ssn_data[index].ni;
1.4较长的语句( >80 字符)要分成多行书写。
说明:
以下情况应分多行书写:
1)长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行
要进行适当的缩进,使排版整齐,语句可读。
2)若函数或过程中的参数较长,则要进行适当的划分。
3)循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式
要在低优先级操作符处划分新行,操作符放在新行之首。
1.5 不允许把多个短语句写在一行中,即一行只写一条语句。
说明:
一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释
1.6 if、for 、do、 while 、case 、switch 、default等语句自占一行 ,且 if 、for 、do 、while 等语句的执行语句部分无论多少都要加括号{}
1.7 代码行之内应该留有适当的空格
说明:
采用这种松散方式编写代码的目的是使代码更加清晰。代码行内应该适当的使用空格, 具体如下:
1)关键字之后要留空格。象 const、virtual、inline、case 等关键字之后至少要留一
个空格, 否则无法辨析关键字。象 if、for、while 等关键字之后应留一个空格再跟左
括号( , 以突出关键字。
2)函数名之后不要留空格, 紧跟左括号’(’ , 以与关键字区。
3)( 向后紧跟, )、,、 ; 向前紧跟, 紧跟处不留空格。
4) , 之后要留空格,如 Function(x, y, z)。如果 ; 不是一行的结束符号, 其后也要留空格,如 for (initialization; condition;update)。
5)值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“ =”、“ +=”
“ >=”、“ <=”、“ +”、“ *”、“ %”、“ &&”、“ ||”、“ <<”、“ ^”等二元操作符
的前后应当加空格。
6)一元操作符如“ !”、“ ~”、“ ++”、“ --”、“ &”( 地址运算符) 等前后不加
空格。
7)象“[ ]”、“ .”、“ ->” 这类操作符前后不加空格。
1.8 程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数的开始、类的定义、结构的定义、枚举的定义以及 if、for、do、while、switch、case 语句中的程序都要采用如上的缩进方式。
2 注释
2.1 源文件头部应进行注释,列出:生成日期、作者、模块目的/功能等。
2.2 函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值等。
2.3 注释应该和代码同时更新,不再有用的注释要删除。
2.4 注释的内容要清楚、明了,不能有冗义性。
2.5 避免在注释中使用非常用的缩写或者术语。
2.6 注释的版式
说明:注释也需要与代码一样整齐排版
1)注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的
注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。
2)注释与所描述内容进行同样的缩排。
3)将注释与其上面的代码用空行隔开。
4)变量、常量、宏的注释应放在其上方相邻位置或右方
2.7 对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理意义。
2.8 数据结构声明,如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面:对结构中的每个域的注释可放在此域的右方。
2.9 对重要变量的定义需编写注释,特别是全局变量更应有较详细的注释,包括对其功能、取值范围、以及存取时注意事项等的说明。
2.10 分支语句需编写注释。
2.11 源程序中有效注释量应控制在20%~30%之间。
3 标识符命名
3.1 命名尽量使用英文单词,力求简单清楚,避免使用引起的误解的词汇和模糊的缩写,使人产生误解。
3.2 常量、宏和模板名采用全大写的方式,每个单词间用下划线分隔。
3.3 对于变量命名,禁止取单个字符(如i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k做局部循环变量是允许的。
说明:
变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如 i 写成 j),而编译
时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。
6.4 不要使用数字或比较奇怪的字符来定义标识符。
3.5 函数名以大写字母开头,采用谓-宾结构(动-名),且应反映函数执行什么操作以及返回什么内容。
3.6 类、结构、联合、枚举的命名须分别以C、S、U、E开头,其他部分遵从一般变量命名规范。
4 可读性
4.1 用括号明确表达式的操作顺序,避免使用默认优先级。
4.2 不要编写太复杂、多用途的复合表达式。
4.3 涉及物理状态或者含有物理意义的常量,避免直接使用数字,必须用有意义的枚举或常量来代替。
4.4 禁止使用难以理解,容易产生歧义的语句。
5 变量、结构
5.1 尽量少使用全局变量,尽量去掉没必要的公共变量。
说明:
公共变量是增大模块间耦合的原因之一,故应减少没必要的公共变量以降低模块间的耦合度。
5.2 变量,特别是指指针变量,被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。
说明:在 C/C++中引用未经赋值的指针,经常会引起系统崩溃
5.3 仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间,并减少引起的误用现象。
说明:
合理排列结构中元素顺序,可节省空间并增加可理解性。
5.4 留心具体语言及编译器处理不同数据类型的原则及有关细节。
说明:
如在 C 语言中,static 局部变量将在内存“数据区”中生成,而非 static 局部变量将在“堆栈”中生成。这些细节对程序质量的保证非常重要。
5.5 尽量减少没有必要的数据类型默认转换与强制转换。
说明:
当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。
5.6 当声明用于发布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题。
说明:
1)在 Intel CPU 与 SPARC CPU,在处理位域及整数时,其在内存存放的“顺序”正
好相反。
2)在对齐方式下,CPU 的运行效率要快一些。
6 函数、过程
6.1 调用函数要检查所有可能的返回情况,不应该的返回情况要用ASSERT来确认。
6.2 编写可重入函数时应注意局部变量的使用(如编写C/C++语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。
说明:
编写 C/C++语言的可重入函数时,不应使用 static 局部变量,否则必须经过特殊处理,才能使函数具有可重入性。
6.3 调用公共接口函数时,调用者有保障调用参数符合要求的义务。作为一种防御性的编程风格,被调用函数也应该对传入参数做必要的安全检查。
6.4 函数的规模尽量限制在100行以内。
6.5 一个函数仅完成一个功能。
6.6 尽量写类的构造、拷贝构造、析构和赋值函数,而不使用系统缺省的。
说明:
编译器以“位拷贝”的方式自动生成缺省的拷贝构造函数和赋值函数 ,倘若类中有指针变量,那么这两个缺省的函数就隐了错误。
例:
假设有以下的类定义:
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String&other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
String a , b ;
如果将 a 赋给 b,缺省赋值函数的“位拷贝”意味着执行 b.m_data = a.m_data。这
将造成以下的错误:
1)b.m_data 原有的内存没被释放,造成内存泄露;
2)b.m_data 和a.m_data 指向同一块内存,a 或 b 任何一方变动都会影响另一方;
3)在对象被析构时,m_data被释放了两次。
6.7 对于不需要拷贝构造函数时,应显示地禁止它,避免编译器生成默认的拷贝构造函数。
例:
class CObject
{
public:
CObject();
private:
CObject & CObject(const CObject rhv) ; // 定义但不实现
}
6.8 谨慎使用与程序运行的环境相关的系统函数。
例:如 strxfrm ()和 strcoll () ,这两个函数依赖于 LC_COLLATE 的设置。如果进程所运行的环境变量没有与开发环境一样设置,可能会产生错误的结果。
6.9 禁止编写依赖于其他函数内部实现的函数。
说明:
此条为函数独立性的基本要求。由于目前大部分高级语言都是结构化的,所以通过具体语言的语法要求与编译器功能,基本就可以防止这种情况发生。但在汇编语言中,由于其灵活性,很可能使函数出现这种情况。
6.10 检查函数所有参数与非参数的有效性。
说明:
1)函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,
即非参数输入。函数在使用输入之前,应进行必要的检查。
2)不应该的入口情况要用 ASSERT 来确认。
3)有时候不处理也是一种处理,但要明确哪些情况不处理。try...catch 是一种常用的不处理的处理手段。
6.11 函数实现中不应改变内容的参数要定义成const。
例:
int GetStrLen(const char*);
int GetNumberCount(const CString&);
6.12 函数的返回值要清楚、明了、准确,防止使用者误用、理解错误或忽视错误返回码。