编码规范标准
一、命名风格
- 驼峰风格(CamelCase):
大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开。按连接后的首字母是否大写,又分: 大驼峰(UperCamelCase)和小驼峰(lowerCamelCase)。 - 内核风格(unix_like):
单词全小写,用下划线分割。如:‘test_result’。 - 匈牙利风格:
在‘大驼峰’的基础上,加上前缀;前缀用于表达类型或用途。如:‘uiSavedCount’, ‘bTested’。
二、命名规范
2.1 变量命名
变量命名采用匈牙利风格,如:
int nFileSize;
string sFilePath;
char *pFileName;
CDateTime dateTimeToday;
常用的匈牙利前缀表:
| 属性部分 | 前缀 |
|---|---|
| 全局变量 | g_ |
| 常量 | c_ |
| 成员变量 | m_ |
| 静态变量 | s_ |
| 类型部分 | 前缀 |
| 数组 | a |
| 指针 | p |
| 函数 | fn |
| 无效 | v |
| 句柄 | h |
| 整型 | n |
| 布尔 | b |
| 浮点型 | f |
| C字符串 | sz |
| 字节 | by |
| string | s |
| vector | vec |
| list | list |
| map | map |
2.2 函数命名
函数命名采用小驼峰风格(优先考虑动词+名词),如:
createFile();
getUrl();
printResult();
2.3 源文件命名
源文件命名采用大驼峰风格,和文件内部的类名保持一致,去掉“C”前缀,如:
/* 实现文件采用.cpp后缀名 */
FileTool.cpp
/* 头文件采用.h后缀名 */
FileTool.h
2.4 类名
类名采用大驼峰风格,统一加前缀“C”,如:
class CFileTool
{
};
class CDateTime
{
};
2.5 宏名
宏名采用全大写 + 下划线分割单词的风格,如:
#define MAX_PATH (260)
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
头文件防御宏:文件名按单词分割,用下划线拼接,H后面两个下划线再拼接当前日期
#ifndef FILE_TOOL_H__20210513
#define FILE_TOOL_H__20210513
#endif /* FILE_TOOL_H__20210513 */
2.6 结构体名
结构体名采用全大写 + 下划线分割单词的风格,最后添加一个“_T”,如:
typedef struct tagFILE_INFO_T {
string sFileName;
int nFileSize;
struct tagFILE_INFO_T *pNext;
} FILE_INFO_T;
三、代码排版风格
使用K&R缩进风格,K&R风格左大括号跟随语句放行末,右大括号独占一行。对于空函数体,可以将大括号放在同一行。
3.1 if语句
if语句必须要使用大括号,即便只有一条语句。
if (objectIsNotExist) { return CreateNewObject(); }禁止if/else/else if写在同一行
if (someConditions) {...} else {...} /* Bad: else与if在同一行 */
3.2 循环语句
和if语句类似,我们要求for/while循环语句必须加上大括号,即使循环体是空的,或者循环语句只有一条。
如果循环体是空的,应该使用空的大括号,而不是使用单个分号。
for (int i = 0; i < someRange; i++) {
...
}
while (someCondition) {
...
}
3.3 switch语句
switch语句的case/default要缩进一层。
switch (var) {
case 0: {
doSomething1();
}
break;
case 1: {
doSomething2();
}
break;
default: {
....
}
break;
}
3.4 函数定义
函数定义也采用K&R风格,并且保持首行空一行,如:
int getFileSize(const string& sFilePath) {
int nFileSize;
...
}
四、注释
**规则:*注释采用/ */形式,为避免中文的乱码问题,建议注释内容统一采用英文描述。
4.1 函数头注释
函数头注释统一放在函数声明或定义上方,使用如下风格:
/* get filesize
**/
int getFileSize(const string& sFilePath);
函数尽量通过函数名自注释,按需写函数头注释。不要写无用、信息冗余的函数头;不要写空有格式的函数头。
/* write string
return writed length
**/
int writeString(const char *pBuf, int nLen);
4.2 代码注释
**规则:**代码注释优先考虑放于对应代码的上方,特殊情况可以放于右侧。
**规则:**注释符与注释内容间要有1空格;右置注释与前面代码至少1空格。
**规则:**放于代码上方的注释,应该保持和对应代码一样的缩进。
/* 这是单行注释 */
int doSomething();
/* 这是多行注释
这是多行注释
**/
int doSomething();
/* 右置格式在适当的时候,上下对齐会更美观 */
const int c_Const = 100; /* 相关的同类注释,可以考虑上下对齐 */
const int c_AnotherConst = 200; /* 上下对齐时,与左侧代码保持间隔 */
**规则:**在条件编译的结束行右方加注释标记,以表明某条件编译块的结束。
#ifdef FLAG_XXX
if (...) {
...
while (index < MAX_INDEX) {
...
}
}
#endif /* FLAG_XXX */
4.3 全局变量注释
全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。
/*
The ErrorCode when SCCP translate
Global Title failure, as follows
0 - SUCCESS
1 - GT Table error
2 - GT error
Others - no use
only function SCCPTranslate() in
this modual can modify it, and other
module can visit it through call
the function GetGTTransErrorCode()
**/
BYTE g_byGTTranErrorCode;
4.4 数据结构注释
**规则:**数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。
/* sccp interface with sccp user primitive message name */
enum SCCP_USER_PRIMITIVE
{
N_UNITDATA_IND, /* sccp notify sccp user unit data come */
N_NOTICE_IND, /* sccp notify user the No.7 network can not transmission this message */
N_UNITDATA_REQ, /* sccp user's unit data transmission request */
};