C编码规范.docx
《C编码规范.docx》由会员分享,可在线阅读,更多相关《C编码规范.docx(38页珍藏版)》请在冰豆网上搜索。
![C编码规范.docx](https://file1.bdocx.com/fileroot1/2023-1/8/e47c49e6-341a-4888-985c-68c088f1af6b/e47c49e6-341a-4888-985c-68c088f1af6b1.gif)
C编码规范
北京四方继保自动化
股份有限公司
作业指导书
文件名称:
C++编码规范
文件编号:
SF-研发中心-0X00
编制
日期
审核
日期
批准
日期
1.
目的
良好的编程风格是提高程序可靠性非常重要的手段,也是在大的软件项目中多人合作开发的基础。
为了提高我公司C++源程序的质量和可维护性,通过本规范定义来规避不好的编程风格,增强代码的可读性与可维护性,以便于自己和他人阅读。
2.适用范围
本规范适用于软件开发中心所开发的后台软件、主站系统平台及应用软件的C++编码。
3.职责
编码人员:
遵照本编码规范进行代码编写。
代码审查人员:
执行代码走查,确认实际代码与编码规范的符合性。
4.相关文件
《高质量C++编程指南》
《软件中心源代码编制规范》
《C&C++编程规范》
《ZDH2004101401-自动化室编程规范(C及C++部分)》
《软件中心源代码编制规范》
5.定义
无
6.编码规范
第一章概述
1.1前言
为了保证软件程序的质量,提高程序的可维护性和可测试性,特制定本C++编程规范。
本规范主要规定了公司软件研发中心C++程序的编码内容及规则,适用于公司所有使用C++语言开发的高级应用软件模块和软件产品。
本规范中的举例,只是针对具体的某一条规范而加以说明,有可能并不符合其他的规范,例如变量定义的举例,对变量的定义做了说明,但在规范的其它举例中,并没有使用规定的定义方法,请使用者加以注意。
规范中的某些内容是属于必须执行的,标有【规范】字样;某些内容是属于建议性的,标有【建议】字样。
1.2规范制定原则
♦方便代码的交流和维护。
♦只规定需要规定的事情,不要强制施加个人喜好或者过时的做法。
♦不影响编码的效率,不与大众习惯冲突。
♦使代码更加美观、阅读更为方便。
♦正确、简单和清晰第一,坚持KISS(KeepItSimpleSoftware)原则。
♦使代码的逻辑更清晰、更易于理解。
第二章文件结构
2.1文件名命名
文件名由基本名和后缀名构成,基本名由不大于8个的字母和数字组成,仅允许用小写字母且以字母开头,基本名应是有意义的名字,应与程序功能相一致。
后缀名由不超过3个字符组成,常见后缀要求如下:
.name.hC++headerfile
.name.cppC++sourcefile
.name.incIncludefile
.name.defDefinition(Declaration)file
.name.cfgCompiledeclarationfile
注意:
严禁使用中文命名文件名。
2.2程序文件内容
2.2.1源程序文件内容
完整的程序文件由若干部分内容构成,各部分内容及一般顺序如下:
a)文件头部注释
说明该文件模块的功能和内容(函数、外部数据说明等)。
应列出版本号,生成日期,作者,主要函数及其功能,修改日志等。
b)各种定义及类型定义
Defines和typedefs,其顺序为:
“constant”macro
“function”macro
typedefs
enums
c)全局(外部)数据说明
Global(external)datadeclarations,其顺序为:
externs
non-staticglobals
staticglobals
如果一组defines仅应用于某一特定的全局数据块(如标志字),则该defines应紧跟在此数据说明之后,或嵌入到结构说明之中。
d)函数模块
功能类似的函数应尽量放在一起,每一函数之前应有函数头部注释,主要提供函数的接口说明,内容包括函数基本功能描述、出入口参数、调用关系,必要时也应包括实现算法。
函数体中,根据需要可有代码块注释,它可对某个代码块的功能、编程技巧及临时变量进行说明。
2.2.2头文件内容
头文件中一般允许放下列内容:
•宏定义
•各种数据结构说明
•typedefs说明
•外部函数说明
•全局变量说明
【规范2.1】头文件(*.h文件)的开始代码部分,一定要加上ifndef/define/endif等预编译判断条件,防止头文件被重复包含。
【规范2.2】用#include格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。
【规范2.3】用#include“filename.h”格式来引用自定义/非标准库的头文件(编译器将从用户的工作目录或者指定的路径开始搜索)。
【规范2.4】头文件名不应与标准函数库名相同。
【规范2.5】头文件中只应包括多个文件都需要的内容。
对于功能不同的内容应放在不同的头文件中。
【规范2.6】如果源文件的个数比较多(超过10个),应该根据软件需要/功能划分将源文件保存在不同的路径下,如下图所示。
【建议2.1】头文件保存在include目录,程序文件保存在source或者src目录(可以根据需要设置为多级目录),资源文件保存在res目录,执行文件保存在bin目录,LIB库文件保存在lib目录,如果有配置文件可以保存在config目录。
【建议2.2】对于某个程序文件所私有的头文件,没有必要公开“声明”。
为了加强信息隐藏,这些私有的头文件可以存放于定义文件的子目录下,如”private/nameP.h”。
【建议2.3】工程目录的各级子目录可以根据某种标准细分为各类子目录,每个子目录都应该包含一个readme文件。
readme文件应该列举目录中包含的子文件及其主要作用说明。
【建议2.4】如果有需要,可以增加其他目录如tmp等等,但建议基本结构不变。
【建议2.5】在头文件中只存放“声明”而不存放“定义”。
【建议2.6】#include中不能包括全路径,尽量采用相对路径。
【建议2.7】给自己的工程一个简短的编码代号如CSFM、CSM等,小组可以统一使用它做代码命名前缀。
第三章排版规则
【规范3.1】在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
相对独立的程序块之间,变量说明之后必须加空行.
【示例】
//空行
voidfunction1(……)
{
……
//空行
while(condition)
{
statement1;
//空行
if(condition)
{
statement2;
}
else
{
statement3;
}
//空行
statement4;
}
……
}
//空行
【规范3.2】变量和运算符间要留有空隙,用一个空格符隔开,便于阅读。
当然,特殊的单目运算符等除外,如“&”、“.”、“->”、“()”及作为指针运算符使用时的“*”。
函数定义和调用中若出现多个参数,前一参数后应紧跟逗号运算符,并用一个空格符与后面参数隔开。
【示例】
inti=0;/*正确*/
inti=0;/*错误*/
a=b*c;/*正确*/
a=b*c;/*错误*/
if((a==b)&&(a!
=c))/*正确*/
if((a==b)&&(a!
=c))/*错误*/
fuc(a,b,c,d)/*正确*/
fuc(a,b,c,d)/*错误*/
for(i=0;i<10;i++)/*正确*/
for(i=0;i<10;i++)/*错误*/
pPointer->a=pPointer->b*pPointer->c/*正确*/
pPointer->a=pPointer->b*pPointer->c/*错误*/
int*pX=&i,y;/*正确,此处y不会被误解为指针*/
int*pX=&i,y;/*错误*/
【规范3.3】一行代码只做一件事情,如只定义一个变量,或只写一条语句。
这样的代码容易阅读,并且方便于写注释。
【示例】
如下例子不符合规范
rect.length=0;rect.width=0;
应如下书写
rect.length=0;
rect.width=0;
【规范3.4】if、for、while、do等语句自占一行,除只有一条语句外,执行语句不得紧跟其后,并加{}。
这样可以防止书写失误。
但要求do…while()结构语句的while子句与}同行且紧跟其后,以区别于while()结构语句。
【示例】
示例:
如下例子不符合规范。
if(pUserCR==NULL)return;
do{}
while(pUserCR==NULL)
应如下书写:
if(pUserCR==NULL)
{
return;
}
do
{
}while(pUserCR==NULL);
【规范3.5】程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。
【规范3.6】{}之内的代码块在“{”右边数格处左对齐。
如果出现嵌套的{},则使用缩进对齐。
【规范3.7】使用4字符长度的缩进风格,而且最好使用tab键缩进代码。
将tab设为4字符长。
【规范3.8】代码行最大长度宜控制在70至80个字符以内。
【规范3.9】长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。
拆分出的新行要进行适当的缩进,使排版整齐,语句可读。
【示例】
if((very_longer_variable1>=very_longer_variable12)
&&(very_longer_variable3<=very_longer_variable14)
&&(very_longer_variable5<=very_longer_variable16))
{
……
}
【规范3.10】应当将修饰符*和&紧靠变量名.
【示例】
char*name;
int*x,y;/*此处y不会被误解为指针。
*/
【规范3.11】关键字之后要留空格。
象const、case等关键字之后至少要留一个空格,否则无法辨析关键字。
象if、for、while等关键字之后应留一个空格再跟左括号“(”,以突出关键字。
【规范3.12】函数名之后不要留空格,紧跟左括号“(”,以与关键字区别。
【规范3.13】“(”向后紧跟,“)”、“,”、“;”向前紧跟,紧跟处不留空格。
【规范3.14】“,”之后要留空格,如Function(x,y,z)。
如果“;”不是一行的结束符号,其后要留空格,如for(initialization;condition;update)。
【规范3.15】“赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”、“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”、“^”等二元操作符的前后应当加空格。
【规范3.16】一元操作符如“!
”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空格。
【规范3.17】象“[]”、“.”、“->”这类操作符前后不加空格。
【规范3.18】对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i<10;i++)和if((a<=b)&&(c<=d))。
【示例】
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();*/
【规范3.19】左括号“(”不要紧靠关键字,中间用一个空格隔开。
【规范3.20】左括号“(”与方法名之间不要添加任何空格。
【规范3.21】没有必要的话不要在返回语句中使用()。
上述三规范举例如下:
【示例】
if(condition)
Array.Remove
(1);
return1;
【规范3.22】左花括号“{”放于关键字或方法名的下一行并与之对齐。
【规范3.23】左花括号“{”要与相应的右花括号“}”对齐。
【规范3.24】通常情况下左花括号“{”单独成行,不与任何语句并列一行。
【规范3.25】if、while、do语句后一定要使用{},即使{}号中为空或只有一条语句。
【建议3.1】尽可能在定义变量的同时初始化该变量(就近原则)。
【示例】
voidfunction(……)
{
inti=0;/*……*/(注释)
intiIntID=-1;/*……*/(注释)
……
for(i=0;i<10;i++)
{
……
if(iIntID<0)
{
……
break;
}
}
……
}
【建议3.2】右花括号“}”后建议加一个注释以便于方便的找到与之相应的“{”。
【示例】
while
(1)
{
if(valid)
{
}/*ifvalid*/
else
{
}/*notvalid*/
}/*endforever*/
第四章代码注释
软件中心开发人员所编制的所有源代码应有良好注释。
最好为英文注释。
【规范4.1】注释应当准确、易懂,防止注释有二义性,注释率达到20%以上。
其中多行注释以/*……*/结构,单行以//结构。
【规范4.2】对于主要的宏、常量、结构,在定义时需要加注释。
【规范4.3】全局变量要有较详细的注释,包括对其功能、取值范围、存取时注意事项等的说明。
【规范4.4】重要循环和条件语句一般要写注释,注释放在这段代码之前,同时要保持相同的层次感。
典型的算法要编写注释,说明算法的原理、使用的公式、必要时列出参考书籍。
【规范4.5】头文件的注释,采用如下格式:
/***********************************************************
*Copyright(C)200X-200X北京四方继保自动化股份有限公司/部门
*Allrightsreserved.
*
*文件名称:
filename.h
*摘要:
功能概述
*当前版本:
<新版本号>,<完成日期****-**-**>,<作者/修改者姓名>,<修改概述>
*
*历史记录:
<旧版本号>,<完成日期****-**-**>,<作者/修改者姓名>,<修改概述>
*V2.0,2004-12-10,张王李,添加函数funcA
*……
*
************************************************************/
#ifndef_INC_FILENAME//预编译,防止头文件被重复引用
#define_INC_FILENAME
#include//标准库的头文件
…
#include“dbType.h”//自定义的非标准库工程通用头文件
…
#include“rtuType.h”//自定义的非标准库本地头文件
…
#definePI3.1415926//宏定义(如不得已而需要的话)
…
structStructName//结构声明(或typedef形式声明)
{
…
};
//FORWARDREFERENCES//引用原型声明等(函数需功能概述)
…
classXX
{
public:
//类声明,注意顺序,先函数再数据
protected:
private:
};
…
//INLINEMETHODS//内嵌函数
voidFunctionName(……);
…
//EXTERNALREFERENCES//外部引用说明
…
#endif
【规范4.6】程序文件的注释,采用如下格式:
/********************************************************************
*Copyright(C)200X-200X北京四方继保自动化股份有限公司/部门
*Allrightsreserved.
*
*文件名称:
filename.cpp(或filename.c)
*摘要:
功能概述
*当前版本:
<新版本号>,<完成日期****-**-**>,<作者/修改者姓名>,<修改概述>
*
*历史记录:
<旧版本号>,<完成日期****-**-**>,<作者/修改者姓名>,<修改概述>
*V2.0,2004-12-10,张王李,添加函数funcA
*……
*
********************************************************************/
//引用头文件
#include“sysPipe.h”//其它模块头文件
#include“sysKrnl.h”//本模块头文件,即本模块需要输出的函数和变量声明
…
//全局变量定义供所有模块引用
intsysBook;
//本地变量定义
staticintgFlag;
//本地函数前置声明
staticvoidLocalFunctionName(…)
……
//注:
当上面的“本地变量定义”和“本地函数前置声明”内容较多时应将上述内容放到private目录下的“本文件名P.h”,即“sysKrnlP.h”头文件中,并在此处引用,如:
#include“private/sysKrnlP.h”
intmain(intargc,char*argv[])//主函数代码
{
……
}
voidsysFunctionName(……)//全局函数代码
{
……
}
…
voidLocalFunctionName(……)//局部函数代码
{
……
}
…
【规范4.7】函数的注释,采用如下格式:
/*
*函数名称:
*函数功能:
*函数入口:
*输入参数:
*输出参数:
*返回值:
*其它说明:
*/
intFunctionName(intarg1,…)
{
……
}
【规范4.8】尽量避免在注释中使用缩写,特别是不常用缩写。
【规范4.9】注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
【规范4.10】注释语言用中、英文兼有,建议多使用中文。
严禁英文和拼音混用。
在使用中文时,必须用/**/注释,且*与注释之间留有空格。
【建议4.1】使用良好一致的注释风格,大段注释使用如下格式。
除首末行外每行顶头用”*”标注。
【示例】
/*
*This is the correct format for a multiline comment
* in a section of code.
*
*/
【建议4.2】使用固定的注释提示:
【示例】
TBD:
tobedone
BUG:
表明BUG的存在
LIMITATION:
程序的限制
BUGFIX:
修复BUG记录
DEBUG:
表明所加代码是为了寻找BUG
TRICKY:
表明紧随的代码比较敏感,修改要谨慎
WARNING:
警示
COMPILER:
表明是为了避免编译器的BUG
KLUDGE:
表明这段代码写的并不明智
【建议4.3】对于一段非常庞大的代码体(比如函数),在其结尾处放置一个识别注释很有好处。
【示例】
voidfoo()
{
…
averyverylongfunctionboby
…
}/*foo*/
【建议4.4】用可视的分隔符将相互关联的函数成组。
【示例】
voidfoo()
{
…
}
/************************************/
voidbar()
{
…
}
【建议4.5】在一个文件中宏、结构、变量、函数等声明/定义都放在一起,并且在之前加上注释表明其内容。
【示例】
/*
*以下为宏定义
*/
#define……/*注释*/
/*
*以下为结构体定义
*/
typedefstruct/*注释*/
{
……/*注释*/
}StructName;
/*
*以下为全局变量声明
*/
……
第五章命名规则
【规范5.1】采用大写字母惯例(骆驼式),组成标识符的各个单词以大写字母打头,然后联接起来,同时有一个匈牙利式的前缀。
【规范5.2】程序中不要出现仅靠大小写区分的相似的标识符。
【示例】
intx,X;/*变量x与X容易混淆*/
【规范5.3】程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。
【规范5.4】尽量避免名字中出现数字编号(标号除外),如Value1,Value2等,除非逻辑上的确需要编号。
【示例】
如下命名,使人产生疑惑。
#define_EXAMPLE_0_TEST_
#define_EXAMPLE_1_TEST_
voidset_sls00(BYTEsls);
应改为有意义的单词命名
#define_EXAMPLE_UNIT_TEST_
#define_EXAMPLE_ASSERT_TEST_
voidset_udt_msg_sls(BYTEsls);
【规范5.5】标识符应当直观且可以拼读,可望文知意,不必进行“解码”。
【规范5.6】标识符最好采用英文单词或其组合,便于记忆和阅读。
切忌使用汉语拼音来命名。
程序中的英文单词一般不会太复杂,用词应当准确。
例如不要把CurrentValue写成NowVa