C语言程序设计代码规范Word下载.docx
《C语言程序设计代码规范Word下载.docx》由会员分享,可在线阅读,更多相关《C语言程序设计代码规范Word下载.docx(16页珍藏版)》请在冰豆网上搜索。
(unsigned)int,(unsigned)long,和一些派生类型:
UINT,ULONG,WORD,DWORD等。
b
bool类型
p
表示指针,在Win32平台下使用p,而不是lp。
h
WindowsAPI内部的各种HANDLE。
sz
char或者char_w类型的数组或者字符串常量。
wnd
Windows窗口,所有MFC窗口对象都以wnd缀开头。
包括:
CView,CDialog,CFrameWnd,CButton等。
pt
POINT,CPoint
clr
COLORREF,其它用来表示颜色的数值类型
dc
CDC类
pen
CPen
brush
CBrush
vector
std:
:
list
list,CList
map
map,CMap
array
CArray
it
iterator
c,w,dw
用于要求明确区分数据类型长度的情况下,如跨平台的网络通讯,或磁盘读取。
注意,尽量使用n作为前缀,而不是这些字符前缀。
对于其他不在上面表中的结构、类等复杂数据类型,特别是不常使用的和不通用的,不使用前缀。
例如:
classPersonJonson;
structDateTimeMyDt;
在应用场合明确的情况下,例如:
简单的局部变量,它的值类型前缀有时可以省略。
具体见下面的例子。
1.1.4复合前缀
根据以上规则,变量根据它所在的作用域、类型、是否是指针,得到一个复合前缀。
charg_szFileName[_MAX_PATH];
//全局字符串变量
char*g_pszFileName;
//全局字符串指针变量:
chars_szFileName[_MAX_PATH];
//静态字符串变量
char*s_pszFileName;
//静态字符串指针变量:
char_s_szFileName[_MAX_PATH];
//局部静态字符串变量
char*_s_pszFileName;
//局部静态字符串指针变量:
charm_szFileName[_MAX_PATH];
//类字符串变量
char*m_pszFileName;
//类字符串指针变量:
charms_szFileName[_MAX_PATH];
//类静态字符串变量
char*ms_pszFileName;
//类静态字符串指针变量:
更多的例子,参见下面按照作用域讨论变量名一节。
1.1.5主体
用于描述变量的上下文意义。
一般地,由首字母大写的一个或者多个单词构成,要求用英语作为描述语言。
如:
FileName,DateTime。
这样就形成了由大小字母夹杂的单词串,这种写法常见于
Windows风格的编码。
注:
全部单词小写,单词之间使用下划线分割,例如:
file_name,date_time。
这种写法常见于UNIX风格的编码。
但是这种命名方式就不能很好地区分缀和主体,所以在本规范中是不推荐的。
单个的变量声明使用单数形式,不加任何冠词。
CFile_file;
数组使用名词复数形式。
CFile_files[3];
一些容器类的作用类似于数组,所以也使用复数命名,例如:
CArray_arrayFiles;
list<
CObject*>
_listObjects;
1.2按作用域分类讨论变量命名
1.2.1参数变量
函数的参数变量要求由后下划线结尾(见作用域缀一节)。
在一些纯数学函数中,也可省去数值类型前缀n,其它类型前缀不能省略。
boolCreate(PCTSTRpszPathName_);
doubleAdd(doublea_,doubleb_);
//值类型前缀省略
1.2.2局部变量
由前下划线开头。
在纯数学函数中,或者简短的上下文中,也可省去数值类型前缀n,其它类型前缀不能省略。
bool_bRet;
char_szBuffer[_MAX_PATH]
//下面是一些值类型前缀省略的例子
int_i;
//常表示循环变量
int_temp;
for(int_i=0;
_i<
_countof(_szBuffer);
_i++)
{
float_a;
//_a的作用域很短,所以可以省略
}
1.2.3全局变量
使用作用域前缀’g_’。
全局变量因为作用域很大,所以命名一定要规范。
名称的主体部分必须能清晰说明变量的意义,并且不得有不规范的缩写。
CWinAppg_Application;
intg_nVersion;
HINSTANCEg_hInstance;
1.2.4静态变量
使用作用域前缀’s_’。
局部静态变量使用前缀’_s_’,注意看下面的例子。
CNcWinApps_App;
ints_nVersion;
HINSTANCEs_hInst;
voidf()
{
staticint_s_nCallTimes;
1.2.5其他例子
下面是变量命名的一些例子:
externHINSTANCEg_hInst;
//全局变量
staticints_nTimer=0;
//全局静态变量
intfunc(intnCounter_,int*pnSize_)//参数变量
//局部变量
long_nTotalItem;
staticlong_s_nCount=0;
int_nVar;
LPSTR_pszBuffer;
TCHAR_szCache[_MAX_PATH];
int_var1;
//省去类型前缀
}
1.3常数
目前本规范对常数类的命名规范还不是非常清晰。
很多常数作用域也很大,类似于全局变量,所以命名一定要规范。
常数分成以下几类讨论。
1.3.1宏定义的常数
#define定义的常数要求用大写字母和下划线混合命名,但是并不强制要求在每个单词之间插入下划线。
#defineLEFT0//okay
#defineRIGHT1//okay
#defineUP_DOWN1//okay
#defineRight1//notrecommended
1.3.2const定义的常数
(未完成)
const常数员命名既可以遵循一般变量命名法则;
也可以遵循常数命名法则;
1.3.3枚举
枚举命名:
枚举名服从一般变量命名法则。
枚举成员命名:
枚举成员名既可以遵循一般变量命名法则;
1.4函数命名规范
函数命名采用大小写夹杂的动宾结构命名。
intGetLastError();
//okay
intgetlasterror();
//全小写,不推荐
intget_last_error();
//全小写,不推荐
intOpenFile();
intFileOpen();
//非动宾结构,不推荐
属于同一类的一组函数可以使用共同前缀来标识。
intNetGetError();
intNetOpen();
intNetClose();
intNetSend();
intNetReceive();
内部实现函数可以使用前下划线作为前缀,例如:
classMyClass
//...
private:
void_init();
};
仅在某一个代码文件使用的内部实现函数应定义为静态函数,这可以避免作用域冲突。
1.5结构命名规范
结构命名:
结构名服从一般变量命名法则。
结构成员命名:
结构变量名服从一般变量命名法则。
structDateTime
intnYear;
intnMonth;
intnDay;
intnHour;
intnMinite;
intnSecond;
本规范不采用对结构成员使用表示结构的前缀。
intdtYear;
//error
intdtMonth;
intdtDay;
//error
intdtHour;
intdtMinite;
intdtSecond;
一般说来,结构中不包含成员函数(偶尔,仅仅包含构造函数是允许的)。
如果希望把结构改造成包含丰富成员函数的对象,那样的话,请使用类(class)。
其命名规范见下面叙述。
1.6类(class)
1.6.1类布局
在类中,推荐先是public节的内容,然后是protected节,最后是private节。
也推荐参考MFC的类布局,使用
//Construction
//Attributes
//Operations
//Overrides
//Implementation
等注释来布局。
1.6.2类成员
类成员变量:
遵循一般变量命名法则,同时要求使用’m_’前缀。
类成员函数:
遵循一般函数命名法则;
嵌套类、枚举、嵌套结构:
遵循一般类、结构命名法则;
综合以上,举一例如:
classMyClass:
publicBaseClass
public:
//first
MyClass();
~MyClass();
protected:
//then
intm_nVar1;
intm_nVar2;
//last
intDoSomething();
2布局规范
需要注意的是,非公共接口的结构、类、常数、函数原形不要放在公共头文件中,而是应该放在私有头文件或实现文件中。
2.1文件标头
文件标头必须包括版权说明、简短介绍。
下面是文件标头的一个例子:
//Copyright(c)NaikyCompany.Allrightsreserved.
//
//Abstract:
//<
someinfohere>
///////////////////////////////////////////////////////////
#include...
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
自VC6.0以来,new/delete操作增加了调试版本,对检测内存泄露非常有帮助。
所以上面的代码包含这部分内容。
2.2函数说明
函数说明是可选的。
可以使用中文或者英文编写。
一般说来,公开接口、公共函数应该有说明,这样便于代码维护。
函数说明有两个地方可以放,一是放在函数声明中,而是放在函数实现中。
这两个地方的函数说明有所不同。
函数声明处的说明:
此处的说明目的是告诉使用者,该函数的用法以及应该注意的问题,应包括函数的作用、入口参数和返回值说明,以及需要注意的声明内容。
下面是一个声明处说明的例子:
//Description:
//[Youcanfillsomedescriptionhere]
//Entries:
//[Parameter1][aboutParameter1]
//[Parameter2][aboutParameter2]
//[Parameter3][aboutParameter3]
//Return:
//[aboutreturnvalue]
//[Note:
]
//[thisisanoptionalsection]
函数实现处的说明:
此处的说明目的是告诉代码维护人员,该函数实现的细节以及在实现过程中需要注意的问题。
以下是摘自实际代码的一个例子:
/****
DESCRIPTION:
Getthedistancefroma3d-pointtoa3d-line.
ALGORITHM:
Alinein3Disgivenbytheparametricvectorwithparametert:
/x0+(x1-x0)*t\
L=|y0+(y1-y0)*t|-----------------------
(1)
\z0+(z1-z0)*t/
Agivenpointis
P=(u1,v1,w1)
Thedistancebetweenthepointandthelineistherefore
r^2=(u1-x0-(x1-x0)*t)^2
+(v1-y0-(y1-y0)*t)^2
+(w1-z0-(z1-z0)*t)^2----------------------
(2)
Tominimizethedistance,take
d(r^2)/dt=0-------------------------(3)
assumethat
a=(x1-x0)u=(u1-x0)
b=(y1-y0)v=(v1-y0)
c=(z1-z0)w=(w1-z0)
therefore
-2a*(u-a*t)-2b(v-b*t)-2c(w-c*t)=0-------(4)
a*u+b*v+c*w
t=------------------------------------------(5)
a*a+b*b+c*c
referenceto
(2),get
r^2=(u-a*t)^2+(v-b*t)^2+(w-c*t)^2-----------(6)
PARAMETERS:
POINT3DDpoint_thegivenpoint
POINT3DDline0_,POINT3DDline1_thegivenline
RETURNS:
thepower2ofthedistance
****/
inlinedoubledistance2_point_line(POINT3DDpoint_,POINT3DDline0_,POINT3DDline1_)
//...
2.3代码布局
代码使用制表符缩进,制表符宽度为4。
代码行宽一般不超过80列(不过,现在的显示器越来越大,阅读更加方便,所以可以考虑把代码行宽设定到100列)。
超过的部分折行到下一行,折行要求缩进一个制表符。
2.3.1空格使用规范
保留字后面空一格。
3;
_i++)//okey
for(int_i=0;
_i++)//notrecommended
while(true)//ok
while(true)//notrecommended
if(a==b)//ok
switch(sw)//ok
双目操作符左右各空一格,括号((,),[,])左右不空格。
a=b=c;
//ok
a=b=c;
//notrecommended
a=(b==c)//ok
a=(b==c)//notrecommended
a=(b==c)//notrecommended
a=(b==(c&
d))//notrecommended
a=b[1]//ok
a=b[1]//notrecommended
if(a==b)//ok
if(a==b)//notrecommended
单目操作符不空格
a++;
//ok
++a;
a*-b;
~a//ok
逗号、分号前面紧贴上一个字符,后面空一格。
func(inta_,intb_,intc_)//ok
func(inta_,intb_,intc_)//notrecommended
func(inta_,intb_,intc_)//notrecommended
for(int_loop=0;
_loop<
_MAX;
_loop++)//ok
_loop<
_loop++)//notrecommended
变量(常量)的类型、名称及其它修饰符之间使用空格,而不是制表符分开,例如:
int_nVar1=0;
//ok
double_nVar2=1.0;
long_nVar3=2;
DWORD_nVar4=0xFFFF;
constfloatc_nMAX_VAL=99999.9999;
int_nVar1=0;
//notrecommended
double_nVar2=1.0;
long_nVar3=2;
DWORD_nVar4=0xFFFF;
2.3.2指针符位置
指针贴近类型,而不是变量。
//followinglinesarefineandrecommendedstyle!
long*_PnVar3=GetPointer();
DWORD*_nVar4=(DWORD*)0xFFFF;
constchar*_pszString=“Thisisateststring”;
//notrecommended!
long*_PnVar3=GetPointer();
DWORD*_nVar4=(DWORD*)0xFFFF;
constchar*_pszString=“Thisisateststring”;
在VC6.0环境下,我们设计了宏StandardFormat用来格式化代码。
可以完成大部分格式化工作。
也可以用VC++中Edit|Advanced|TabifySelection和Edit|Advanced|UntabifySelection命令来格式化代码。
下面是一些推荐布局风格:
//Ex.1
if(a==b)
//somecodehere
//Ex.2
switch(_nSwitchVar)
case1:
{
//somecodehere
int_temp=//...
break;
case2:
f
(2);
case3:
f(3);
default:
assert(false);
不推荐风格:
if(a==b){
3语法风格
避免不好的语法习惯。
3.1关于if
不要在if表达式中使用’=’。
int_a;
if(_a=GetValue())
应该写为:
int_a=GetValue();
if(_a)//orif(_a!
=0)
下面的代码实际上可能并不按你想象的方式运行:
if(d==e)
x=1;
else
func();
3.2变量声明与定义
不要使用未赋初值的变量,尤其是指针:
if(GetSomeValue()==OK)
_a=100;
Func(a);
//atsomecases,“a”hasnotgetaninitialvaluehere
3.3关于宏
不要在宏中使用表达式或者调用函数:
#define__max(a,b)((a)>
(b)?
(a):
(b))
__max(func(),3)//notrecommended!
!
__max(var++,3)//notrecommended!
int_a=func();
__max(_a,3)//okey
尽量使用inline函数代替函数宏。
尽量使用const代替常数宏。
3.4测试代码
一些测试代码要用_DEBUG包围起来。
//badcode!
if(pszBuffer)
ASSERT(strlen(pszBuffer)<
100);
//goodcode
if(