for(initialization;condition;update)
{
dosomething();
}
//空行
other();
for(initialization;condition;update)
dosomething();
other();
图5 风格良好的代码行(左),与风格不良的代码行(右)
15.2.3 尽可能在定义变量的同时初始化该变量。
若变量的引用处与其定义处相隔比较远,变量的初始化易被忘记。
若引用了未被初始化的变量,易导致程序错误。
1示例:
intwidth=10;//定义并初绐化width
intheight=10;//定义并初绐化height
intdepth=10;//定义并初绐化depth
15.3 代码行内的空格
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();
图6 代码行内的空格
15.3.1 关键字之后应留空格。
如if、for、while等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。
15.3.2 函数名之后应不留空格,紧跟左括号‘(’,以与关键字区别。
15.3.3 ‘(’后面应不留空格,‘)’、‘,’、‘;’前面应不留空格。
15.3.4 ‘,’之后应留空格,如Function(x,y,z)。
若‘;’不是一行的结束符号,其后应留空格,如for(initialization;condition;update)。
15.3.5 赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应加空格。
15.3.6 一元操作符如“!
”、“~”、“++”、“--”、“&”(地址运算符)等前后应不加空格。
15.3.7 “[]”、“.”、“->”等操作符前后应不加空格。
对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i<10;i++)和if((a<=b)&&(c<=d))
15.4 对齐
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
}
若出现嵌套的{},则使用缩进对齐,如:
{
…
{
…
}
…
}
图7 风格良好的对齐(左),与风格不良的对齐(右)
15.4.1 程序块应采用缩进风格编写,缩进的空格数为4个。
对于由开发工具自动生成的代码可以有不一致。
15.4.2 对齐只使用空格键,不使用TAB键。
以免用不同的编辑器阅读程序时,因TAB键所设置的空格数目不同而造成程序布局不整齐,不应使用BC作为编辑器合版本,因为BC会自动将8个空格变为一个TAB键,因此使用BC合入的版本大多会将缩进变乱。
15.4.3 程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。
(见图7)
15.5 长行拆分
15.5.1 代码行最大长度宜控制在80个字符以内。
15.5.2 长表达式宜在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。
若函数或过程中的参数较长,也应进行适当的划分。
拆分出的新行应进行适当的缩进,使排版整齐,语句可读(见图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();
}
图8 长行的拆分
15.6 注释
15.6.1 概述
注释分为序言性注释和功能性注释:
11——序言性注释通常置于每一个程序模块的开头部分,给出程序的整体说明,对于理解程序具有引导作用;
12——功能性注释嵌在源程序体中,用以描述其后的语句或程序段在做什么工作。
15.6.2 注释行的数量不得少于整个源程序的1/5。
15.6.3 单行注释原则上不得超过可视窗口宽度。
15.6.4 若代码本来就是清楚的,则不必加注释。
2示例:
i++;//i加1,多余的注释
15.6.5 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。
不再有用的注释应删除。
在存档的某一版本的源代码中不得存在由于调试而留下的大篇注释。
15.6.6 注释应当准确、易懂,防止注释有二义性。
15.6.7 尽量避免在注释中使用缩写,特别是不常用缩写。
15.6.8 注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
15.6.9 在同一函数或模块中的注释应尽量对齐,如下例所示:
3示例:
BOOLbReturnCache;//是否将Cache中的内容返回客户端
HANDLEFileToWrite;//用来写数据的文件
DWORDBytesWritten;//写入的数据长度
15.6.10 当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读(见图9)。
/*
*函数介绍:
*输入参数:
*输出参数:
*返回值:
*/
voidFunction(floatx,floaty,floatz)
{
…
}
if(…)
{
…
while(…)
{
…
}//endofwhile
…
}//endofif
图9 程序的注释
15.6.11 注释与所描述内容进行同样的缩排。
可使程序排版整齐,并方便注释的阅读与理解。
4示例:
如下例子,排版不整齐,阅读不方便。
voidexample_fun(void)
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
应改为如下布局。
voidexample_fun(void)
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
15.6.12 将注释与其上面的代码用空行隔开。
5示例:
如下例子,显得代码过于紧凑。
/*codeonecomments*/
programcodeone
/*codetwocomments*/
programcodetwo
应如下书写
/*codeonecomments*/
programcodeone
/*codetwocomments*/
programcodetwo
15.6.13 函数注释(序言性注释)
15.6.13.1 单元文件宜不超过1000行(包括注释),复杂的组件单元可以不受此限制.
15.6.13.2 每个函数或过程代码必须有注释文字,每个函数体中,每一小功能段都应有注释。
15.6.13.3 函数定义之前必须有对整个函数的描述,注释格式如下
/*****************************************************************************
【函数名称】(必需)
【函数功能】(必需)
【参数】(若有参数则必需注明)
【全局变量】(可选)
【返回值】(若有返回值则必需注明)
【备注】(可选)
【开发者及日期】(若与头文件注释中的开发者为不同的人,则必需注明)
【版本】(若与头文件注释中的版本不同,则必需注明)
【更改记录】(若有修改,则必需注明)
[最后修改]
[修改日期]
更改原因概要
[版本]
【使用情况】(可选)
*****************************************************************************/
注释内容说明:
函数名称:
应包括函数名及参数;
参数:
在本项中标明是输入参数(用[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函数中被调用一次
*****************************************************************************/
15.6.14 程序注释(功能性注释)
15.6.14.1 变量
若变量命名不能充分自注释,则必须注释变量意义;全局变量必须有较详细的注释,包括:
功能、取值范围、存取关系、哪些函数或过程存取它以及注意事项等。
15.6.14.2 数据结构
若命名不能充分自注释,则应注释其意义。
15.6.14.3 判断
注释应说明被检查对象的意义。
15.6.14.4 分支
注释应说明各分支对应的情况。
15.6.14.5 调用函数
注释应说明该函数完成的处理。
15.6.14.6 赋值
注释应说明赋值意义。
16 命名规则
16.1 共性规则
16.1.1 标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
标识符最好采用英文单词或其组合。
16.1.2 标识符的长度应当符合“min-length&&max-information”原则。
16.1.3 命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
16.1.4 程序中不应出现仅靠大小写区分的相似的标识符。
6示例:
intx,X;//变量x与X容易混淆
voidfoo(intx);//函数foo与FOO容易混淆
voidFOO(floatx);
16.1.5 程序中不应出现标识符完全相同的局部变量和全局变量。
16.1.6 变量的名字应当使用“名词”或者“形容词+名词”。
7示例:
floatvalue;
floatoldValue;
floatnewValue;
16.1.7 全局函数的名字宜使用“动词”或者“动词+名词”(动宾词组)。
类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
8示例:
DrawBox();//全局函数
box->Draw();//类的成员函数
16.1.8 宜用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
9示例:
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
16.1.9 尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。
16.1.10 在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产