for(initialization;condition;update)
{
dosomething();
}
//空行
other();
for(initialization;condition;update)
dosomething();
other();
风格良好的代码行(左),与风格不良的代码行(右)
尽可能在定义变量的同时初始化该变量。
若变量的引用处与其定义处相隔比较远,变量的初始化易被忘记。
若引用了未被初始化的变量,易导致程序错误。
:
intwidth=10;//定义并初绐化width
intheight=10;//定义并初绐化height
intdepth=10;//定义并初绐化depth
代码行内的空格
voidFunc1(intx,inty,intz);//良好的风格
voidFunc1(intx,inty,intz);//不良的风格
if(year>=2000)//良好的风格
if(year>=2000)//不良的风格
if((a>=b)&&(c<=d))//良好的风格
if(a>=b&&c<=d)//不良的风格
for(i=0;i<10;i++)//良好的风格
for(i=0;i<10;i++)//不良的风格
for(i=0;I<10;i++)//过多的空格
x=a
a:
b;//良好的风格
x=a
a:
b;//不好的风格
int*x=&y;//良好的风格
int*x=&y;//不良的风格
array[5]=0;//不应写成array[5]=0;
a.Function();//不应写成a.Function();
b->Function();//不应写成b->Function();
代码行内的空格
关键字之后应留空格。
如if、for、while等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。
函数名之后应不留空格,紧跟左括号‘(’,以与关键字区别。
‘(’后面应不留空格,‘)’、‘,’、‘;’前面应不留空格。
‘,’之后应留空格,如Function(x,y,z)。
若‘;’不是一行的结束符号,其后应留空格,如for(initialization;condition;update)。
赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应加空格。
一元操作符如“!
”、“~”、“++”、“--”、“&”(地址运算符)等前后应不加空格。
“[]”、“.”、“->”等操作符前后应不加空格。
对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i<10;i++)和if((a<=b)&&(c<=d))
对齐
voidFunction(intx)
{
…//programcode
}
voidFunction(intx){
…//programcode
}
if(condition)
{
…//programcode
}
else
{
…//programcode
}
if(condition){
…//programcode
}
else{
…//programcode
}
for(initialization;condition;update)
{
…//programcode
}
for(initialization;condition;update){
…//programcode
}
While(condition)
{
…//programcode
}
while(condition){
…//programcode
}
若出现嵌套的{},则使用缩进对齐,如:
{
…
{
…
}
…
}
风格良好的对齐(左),与风格不良的对齐(右)
程序块应采用缩进风格编写,缩进的空格数为4个。
对于由开发工具自动生成的代码可以有不一致。
对齐只使用空格键,不使用TAB键。
以免用不同的编辑器阅读程序时,因TAB键所设置的空格数目不同而造成程序布局不整齐,不应使用BC作为编辑器合版本,因为BC会自动将8个空格变为一个TAB键,因此使用BC合入的版本大多会将缩进变乱。
程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。
(见图7)
长行拆分
代码行最大长度宜控制在80个字符以内。
长表达式宜在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。
若函数或过程中的参数较长,也应进行适当的划分。
拆分出的新行应进行适当的缩进,使排版整齐,语句可读(见图8)。
if((very_longer_variable1>=very_longer_variable12)
&&(very_longer_variable3<=very_longer_variable14)
&&(very_longer_variable5<=very_longer_variable16))
{
dosomething();
}
virtualCMatrixCMultiplyMatrix(CMatrixleftMatrix,
CMatrixrightMatrix);
for(very_longer_initialization;
very_longer_condition;
very_longer_update)
{
dosomething();
}
长行的拆分
注释
概述
注释分为序言性注释和功能性注释:
序言性注释通常置于每一个程序模块的开头部分,给出程序的整体说明,对于理解程序具有引导作用;
功能性注释嵌在源程序体中,用以描述其后的语句或程序段在做什么工作。
注释行的数量不得少于整个源程序的1/5。
单行注释原则上不得超过可视窗口宽度。
若代码本来就是清楚的,则不必加注释。
:
i++;//i加1,多余的注释
边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。
不再有用的注释应删除。
在存档的某一版本的源代码中不得存在由于调试而留下的大篇注释。
注释应当准确、易懂,防止注释有二义性。
尽量避免在注释中使用缩写,特别是不常用缩写。
注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
在同一函数或模块中的注释应尽量对齐,如下例所示:
:
BOOLbReturnCache;//是否将Cache中的内容返回客户端
HANDLEFileToWrite;//用来写数据的文件
DWORDBytesWritten;//写入的数据长度
当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读(见图9)。
/*
*函数介绍:
*输入参数:
*输出参数:
*返回值:
*/
voidFunction(floatx,floaty,floatz)
{
…
}
if(…)
{
…
while(…)
{
…
}//endofwhile
…
}//endofif
程序的注释
注释与所描述内容进行同样的缩排。
可使程序排版整齐,并方便注释的阅读与理解。
:
如下例子,排版不整齐,阅读不方便。
voidexample_fun(void)
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
应改为如下布局。
voidexample_fun(void)
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
将注释与其上面的代码用空行隔开。
:
如下例子,显得代码过于紧凑。
/*codeonecomments*/
programcodeone
/*codetwocomments*/
programcodetwo
应如下书写
/*codeonecomments*/
programcodeone
/*codetwocomments*/
programcodetwo
函数注释(序言性注释)
单元文件宜不超过1000行(包括注释),复杂的组件单元可以不受此限制.
每个函数或过程代码必须有注释文字,每个函数体中,每一小功能段都应有注释。
函数定义之前必须有对整个函数的描述,注释格式如下
/*****************************************************************************
【函数名称】(必需)
【函数功能】(必需)
【参数】(若有参数则必需注明)
【全局变量】(可选)
【返回值】(若有返回值则必需注明)
【备注】(可选)
【开发者及日期】(若与头文件注释中的开发者为不同的人,则必需注明)
【版本】(若与头文件注释中的版本不同,则必需注明)
【更改记录】(若有修改,则必需注明)
[最后修改]
[修改日期]
更改原因概要
[版本]
【使用情况】(可选)
*****************************************************************************/
注释内容说明:
函数名称:
应包括函数名及参数;
参数:
在本项中标明是输入参数(用[in]表示)还是输出参数(用[out]表示);
全局变量:
该函数访问的全局变量和成员全局变量;
版本:
如1.0;
更改记录:
每次改动时增加一行注释,说明更改标识,更改日期,人,版本,更改原因概要;
使用情况:
即函数的调用情况,被调用的次数;
例如:
/*****************************************************************************
【函数名称】
intMy_GetLastModifedTime(CStringstrFileName,char*FileTime,long*cl)
【函数功能】
寻找目标文件,从中读取Last-Modified:
信息、Contene-Length信息
【参数】
FileName[in]指向目标文件(从URL而来,需要转换,与目标文件一一对应)
FileTime[out]获取的Last-Modified:
信息
cl[out]获取的Contene-Length信息
【返回值】
1文件存在,并从中取得Last-Modified:
信息
-1else
【备注】
使用了StrStrI函数,所以必须includeshlwapi.h文件,且在编译的link项中包括shlwapi.li文件
【开发者及日期】
周慈2000-02-05
【版本】
1.0
【修改历史】
[最后修改]黄何寅
[2000-03-26]
修改打开文件的模式,从OPEN_ALWAYS改为OPEN_EXISTING
[2000-03-28]
返回的时间字符串,最后一位不需要'\n',而且清除后面的所有空格
[版本]
1.2
【使用情况】
仅在ProxyThread函数中被调用一次
*****************************************************************************/
程序注释(功能性注释)
变量
若变量命名不能充分自注释,则必须注释变量意义;全局变量必须有较详细的注释,包括:
功能、取值范围、存取关系、哪些函数或过程存取它以及注意事项等。
数据结构
若命名不能充分自注释,则应注释其意义。
判断
注释应说明被检查对象的意义。
分支
注释应说明各分支对应的情况。
调用函数
注释应说明该函数完成的处理。
赋值
注释应说明赋值意义。
命名规则
共性规则
标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
标识符最好采用英文单词或其组合。
标识符的长度应当符合“min-length&&max-information”原则。
命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
程序中不应出现仅靠大小写区分的相似的标识符。
:
intx,X;//变量x与X容易混淆
voidfoo(intx);//函数foo与FOO容易混淆
voidFOO(floatx);
程序中不应出现标识符完全相同的局部变量和全局变量。
变量的名字应当使用“名词”或者“形容词+名词”。
:
floatvalue;
floatoldValue;
floatnewValue;
全局函数的名字宜使用“动词”或者“动词+名词”(动宾词组)。
类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
:
DrawBox();//全局函数
box->Draw();//类的成员函数
宜用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
:
intminValue;
intmaxValue;
intSetValue(…);
intGetValue(…);
下面是一些在软件中常用的反义词组。
add/removebegin/endcreate/destroy
insert/deletefirst/lastget/release
increment/decrementput/get
add/deletelock/unlockopen/close
min/maxold/newstart/stop
next/previoussource/targetshow/hide
send/receivesource/destination
cut/pasteup/down
尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。
在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。
对接口部分的标识符应该有更严格限制,防止冲突。
如可规定接口部分的变量与常量之前加上“模块”标识等。
一般命名规则
类名和函数名、结构名、typedef的名用大写字母开头的单词组合而成。
:
classNode;//类名
classLeafNode;//类名
voidDraw(void);//函数名
voidSetValue(intvalue);//函数名
typedefstructSTUDENT;//typedef
变量和参数应用小写字母开头的单词组合而成。
:
BOOLflag;
intdrawMode;
常量应全用大写的字母,并用下划线分割单词。
:
constintMAX=100;
constintMAX_LENGTH=100;
静态变量应加前缀s_(表示static)。
:
voidInit(…)
{
staticints_initValue;//静态变量
…
}
若必须使用全局变量,则全局变量应加前缀g_(表示global)。
:
intg_howManyPeople;//全局变量
intg_howMuchMoney;//全局变量
类的数据成员应加前缀m_(表示member),以避免数据成员与成员函数的参数同名。
:
voidObject:
:
SetValue(intwidth,