编程规范Word文件下载.docx
《编程规范Word文件下载.docx》由会员分享,可在线阅读,更多相关《编程规范Word文件下载.docx(16页珍藏版)》请在冰豆网上搜索。
6、循环要完成的工作,写在循环体中,循环控制部分尽量简单。
下面这种代码不允许出现:
for(cx=x,cy=y;
r=cx%cy;
cx=cy,cy=r);
while(scanf("
%d"
&
n),n);
7、尽量不要使用goto语句。
goto语句只能在多重循环嵌套的最内层向最外层跳出时使用,且循环次数非常多(百万次级数以上)。
2.3请及时更新旧代码
受产品的资金、时间、范围的约束,你可能写出能工作但结构不优美、执行效率不高的代码,这情有可原,但不要对这种代码置之不管。
2.4保持良好的软件结构
一般情况下,好的软件结构具备如下特征:
●顶层函数的扇出较高
●中层函数的扇出较少
●底层函数则归入到公共模块中
2.5预留调试接口,对可能存在的错误作出预防
3.文件命名与组织
3.1扩展名
表1常用文件扩展名
文件类型
扩展名
备注
C源文件
.c
小写
C++源文件
.cpp
C/C++头文件
.h
3.2.常用文件名
表2常用文件名
文件名称
用途
Makefile
Makefile的首选名称。
RELEASE
程序发行说明,描述各个版本的主要更改、问题解决状况、尚未解决的问
题等等
README
总结项目目录的内容
ChangeLog
代码修改记录,详细描述对每个源文件所做的修改,最好精确到函数级别
4.代码结构
4.1文件头
文件头是嵌入在C/C++头文件或源文件中,在文件首部的注释块,一般包含如下信息:
●公司或组织的名称
●地址
●版权说明
●开发人员
●模块目的/功能
●文件版本
●修改日志
4.2C/C++头文件
头文件的布局如下:
文件头
版本历史
常量定义
全局宏定义
是否在头文件包含文件头,这有些争议,有些头文件较简单,可不必包含文件头。
但一般说来,公共头文件(接口/原型)需要带有文件头。
4.3C/C++源文件
源文件也即实现文件,其布局:
文件头
#include区
#define区
宏定义区(Macros)
本地数据类型定义区(Localdatatypes)
本地变量区(Localvariables)
本地表(Localtables)
本地函数原型(Localfunctionprototypes)
全局函数(Globalfunctions)
局部函数(Localfunctions)
5.排版
5.1代码行宽度
推荐每行的代码宽度限制在80个字符内。
80个字符限制是由于旧显示器的约束,可视范围只有80个字符。
较长的语句(>
80字符),要分成多行书写,,表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
推荐:
太长的表达式可以分成多个较短的表达式来书写。
5.2TAB字符的使用
请将编辑器的TAB字符占位设置为4个空格。
5.3缩进
函数、结构、循环、判断等语句都需要采用缩进,缩进请使用一个TAB(4个空格)。
5.4空行
相对独立的程序块之间、变量说明之后必须加一个空行。
但不要随意添加无谓的空行。
例如,下面的写法不正确:
voidfunction1()
{
intvar1,var2;
var1=1;
var2=2;
}
正确的书写方法是:
intvar1,var2;
5.5不允许把多个短语句写在一行中
示例:
如下例子不符合规范
rect.length=0;
rect.width=0;
应如下书写
rect.length=0;
5.6添加空格
在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;
进行非对等操作时,如果是关系密切的立即操作符(如->
),后不应加空格。
示例如下:
1、逗号、分号只在后面加空格
inta,b,c;
2、比较操作符,赋值操作符"
="
、"
+="
,算术操作符"
+"
%"
,逻辑操作符"
&
"
,
位域操作符"
<
、"
^"
等双目操作符的前后加空格。
if(current_time>
=MAX_TIME_VALUE)
a=b+c;
a*=2;
a=b^2;
3、"
!
~"
++"
--"
(地址运算符)等单目操作符前后不加空格。
*p='
a'
;
//内容操作"
*"
与内容之间
flag=!
isEmpty;
//非操作"
p=&
mem;
//地址操作"
与内容之间
i++;
//"
"
4、"
->
."
前后不加空格。
p->
id=pid;
//"
指针前后不加空格
5、if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。
if(a>
=b&
c>
d)
5.7对于赋值语句,等号和数值保持垂直对齐。
(推荐)
示例:
DispSegTblIx=0;
DispDigMsk=0x80;
DispScale=1.25;
6.注释
6.1每一个注释都必须有用.
6.2对于函数要给出必要的注释
必须注释出:
:
函数的名称、功能、入口参数、出口参数、返回值、调用说明。
除非有把握使用英语明确表达你的用意。
一般情况下使用中文。
/**
*sample_func–summarythisfunction
*@param1:
descriptionofparam1
*@param2:
descriptionofparam2
*Detaildescripttheusuageofsample_func.
**/
intsample_func(intparam1,intparam2);
上面的例子中,每一行前面的那个*号,由编辑器自动添加,如果你的编辑器不会自动添加,可以不必添加。
6.3注释的修改
边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。
不再有用的注释要删除。
6.4尽可能使用尾部注释
voidClkUpdateTime(void)
if(ClkSec>
=CLK_MAX_SEC)//Updatetheseconds
ClkSec=0;
if(ClkMin>
=CLK_MAX_MIN)//Updatetheminutes
ClkMin=0;
if(ClkHour>
=CLK_MAX_HOURS)//Updatethehours
ClkHour=0;
6.5注释的格式尽量统一
尾部注释建议使用“//”,头部使用块注释“/**/”
7.标识符命名约定
7.1一般约定
1、用#define或者const定义的符号常量所有字符都必须大写。
2、局部变量、成员变量和函数名采用驼峰规则,除第一个单词的首字母小写外,其它单词的首字母大写。
3、类名采用驼峰规则,所有单词首字母都要大写。
4、全局变量要以下划线作为首字符。
(但尽量不要使用全局变量)
5、所有用户自定义标识符尽量以有意义的单词组合作为名称。
6、循环计数器可以使用i,j,k这类短名称
7、指针类型以p开头。
7.2缩写与助记符
太长的单词可以使用缩写或者助记符形式,基本规则是取其中的3-4个字母,具体是:
1、首尾两个字母,中间取每个音节的首个字母(1-2个);
2、或者取最前面的3-4个字母;
3、一般不取元音字母;
4、如果已经有了公认的缩写形式,则以公认的形式为准,不受上面3条规则限制。
表3常用单词缩写表
单词
缩写
Argument
Arg
Buffer
Buf
Clear
Clr
Clock
Clk
Compare
Cmp
Configuration
Cfg
Context
Ctx
Control
Ctl
Delay
Dly
Device
Dev
Disable
Dis
Display
Disp
Enable
En
Error
Err
Function
Fnct
Hexadecimal
Hex
HighPriorityTask
HPT
I/OSystem
IOS
Initialize
Init
Mailbox
Mbox
Manager
Mgr
Manual
Man
Maximum
Max
Message
Msg
Minimum
Min
Multiplex
Mux
OperationgSystem
OS
Overflow
Ovf
Parameter
Param
Pointer
Ptr
Previous
Prev
Priority
Prio
Read
Rd
Ready
Rdy
Register
Reg
Sehedule
Sched
Semaphore
Sem
Stack
Stk
Synchronize
Sync
Timer
Tmr
Trigger
Trig
Write
Wr
8.变量使用
1、尽可能少地定义全局变量;
2、局部变量与全局变量不要同名;
3、严禁使用未经初始化的变量作为右值;
9.函数设计和使用
9.1函数设计
1、明确函数功能,精确(而不是近似)地实现函数设计。
2、尽量不使用递归函数,尽可能从算法上消除递归,能用迭代的,坚决不能使用递归。
如果不能消除递归,则用自行管理堆栈的形式来消除形式上的递归。
3、函数的规模尽量限制在200行以内(不包括注释和空格行)。
4、一个函数执行一个任务或功能,一个复杂的功能可由多个功能单一的函数实现。
5、函数的功能是可以预测的,也就是只要输入数据相同就应产生同样的输出。
除非该函数已经明确表示使用了随机算法。
说明:
带有内部“存储器”的函数的功能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。
这样的函数即不易于理解也不利于测试和维护。
6、尽量不要编写依赖于其他函数内部实现的函数。
此为函数独立性的基本要求。
7、如果多段代码重复做同一件事情,那么在函数的划分上可能存在问题。
若此段代码各语句之间有实质性关联并且是完成同一件功能的,那么可考虑把此段代码构造成一个新的函数。
8、功能不明确较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上级函数中,而不必单独存在。
说明:
模块中函数划分的过多,一般会使函数间的接口变得复杂。
所以过小的函数,特别是扇入很低的或功能不明确的函数,不值得单独存在。
9、设计高扇入、合理扇出(小于7)的函数。
扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;
而扇出过小,如总是1,表明函数的调用层次可能过多,这样不利程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。
函数较合理的扇出(调度函数除外)通常是3-5。
扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。
扇出太小,可把下级函数进一步分解多个函数,或合并到上级函数中。
当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。
扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。
公共模块中的函数及底层函数应该有较高的扇入。
10、函数除了有正常的返回值,也应该有表示出错情况的返回值。
如果二者不可兼得,应该使用异常机制。
9.2函数调用
1、对于所调用函数的错误返回码要仔细、全面的处理。
2、应明确规定对接口函数参数的合法性检查由函数的调用者还是由接口函数本身负责。
缺省是由函数编写者负责,除非函数内部无法判断参数的合法性(比如指针所指向的空间大小,这时调用者必须保证空间足够)。
3、非调度函数应减少或限制控制参数,尽量只使用数据参数。
本建议目的是防止函数间的控制耦合。
调度函数是指根据输入的消息类型或控制命令,来启动相应的函数,而本身并不完成具体功能。
控制参数是指改变函数功能行为的参数,即函数要根据此参数来决定具体怎样工作。
非调度函数的控制参数增加了函数间的控制耦合,很可能使函数间的耦合度增大,并使函数的功能不唯一。
如下函数构造不太合理
intadd_sub(inta,intb,unsignedcharadd_sub_flg)
if(add_sub_flg==INTEGER_ADD)
{
return(a+b);
}
else
return(a-b);
更好的做法是分为两个函数
intadd(inta,intb)
intsub(inta,intb)
4、在调用函数填写参数时,应尽量减少没有必要的默认数据类型转换或强制数据类型转换,因为数据类型转换或多或少存在危险(建议:
将编译器的所有警告开关全部打开,让编译器帮助发现此类危险)。
10.宏
可以使用宏来定义符号常量,但应该尽量减少用宏来定义表达式,切不可使用宏来代替函数。
定义表达式时,要使用完备的括号。
11.头文件
11.1防止重复包含
为防止重复包含,请在头文件加上条件INCLUDE。
示例:
#ifndef__LINUX_FILE_H
#define__LINUX_FILE_H
#include<
asm/atomic.h>
linux/posix_types.h>
linux/spinlock.h>
#endif
11.2仅引用需要的头文件
当模块的实现依赖于其他模块时,要这样做:
尽量在C/C++源文件手工引用多个头文件,仅引用你需要调用的头文件。
而不要这样做:
把多个头文件包含在一个头文件中,源文件仅包含这一个头文件。
12.可测性
12.1调试信息的控制
要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。
示例,以下使用DEBUG作为调试开关,输出调试信息
#ifdefDEBUG
#defineDPRINTF(s)PRINTF(s)
#else
#defineDPRINTF(s)
如果要将调试开关打开,只需要传递给编译器”-DDEBUG”的标记。
测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关)。
12.2调试信息的格式
调测打印出的信息串的格式要有统一的格式。
信息串中至少要有所在模块名(或源文件名)及行号。
统一的调测信息格式便于分析,特别是用程序来辅助分析。
12.3使用断言
断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否则应报告),它可以快速发现并定位软件问题,同时对系统错误进行自动报警。
断言可以对在系统中隐藏很深,用其它手段极难发现的问题进行定位,从而缩短软件问题定位时间,提高系统的可测性。
实际应用时,可根据具体情况灵活地设计断言。
正式软件产品中应把断言及其他调测代码去掉(即把有关的调测开关关掉)。
在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响(即有测试代码的软件和关掉测试代码的软件,在功能行为上应一致)。
13.质量保证
13.1代码质量保证优先原则
1、正确性,指程序要实现设计要求的功能。
2、稳定性、安全性,指程序稳定、可靠、安全。
3、可测试性,指程序要具有良好的可测试性。
4、规范/可读性,指程序书写风格、命名规则等要符合规范。
5、全局效率,指软件系统的整体效率。
6、局部效率,指某个模块/子模块/函数的本身效率。
7、个人表达方式/个人方便性,指个人编程习惯。
13.2只引用属于自己的存贮空间
若模块封装的较好,那么一般不会发生非法引用他人空间的情况。
13.3防止引用已经释放的内存空间
在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块(如C语言指针),而另一模块在随后的某个时刻又使用了它。
要防止这种情况发生,除了多测试,别无办法。
13.4防止内存泄漏
函数中分配的内存,在函数退出之前要释放。
用malloc函数分配的内存,要用free释放;
用new分配的内存,要用delete释放。
为了最大程度上避免内存泄漏的出现,推荐:
1、如果动态申请的内存只在本函数内使用,请使用向量vector来操作。
2、如果需要全局使用或者跨函数使用动态内存,请使用模板类auto_ptr。
但不管使用何种方法,程序编写成功后,还需要利用第三方工具进行跟踪测试。
13.4防止内存操作越界
内存操作主要是指对数组、指针、内存地址等的操作。
内存操作越界是软件系统主要错
误之一,后果往往非常严重,所以当程序进行这些操作时一定要仔细小心。
为了防止指针越界,应该尽量少使用指针,如果仅仅是为了使用连续的内存空间,完全可以用vector来代替。
如果定义二级指针是为了处理字符串数组,可以直接使用string数组。
为了防止下标越界,需要在使用前进行下标合法性检测,更省事的方法是用vector代替C++的原生数组。
13.5提高程序健壮性
1、程序员需要认真处理程序所能遇到的各种出错情况。
2、系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用;
3、要对加载到系统中的数据进行一致性检查;
4、编程时,不能随心所欲地更改不属于自己模块的有关设置如常量、数组的大小等。
5、严禁随意更改其它模块或系统的有关设置和配置。
6、不能随意改变与其它模块的接口。
7、编程时,要防止“差1”错误。
此类错误一般是由于把“<
=”误写成“<
”或“>
=”误写成“>
”等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心。
当编完程序后,应对这些操作符进行彻底检查。
8、要时刻注意易混淆的操作符。
当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。
形式相近的操作符最容易引起误用,如C/C++中的“=”与“==”、“|”与“||”、“&
”与“&
”等,若拼写错了,编译器不一定能够检查出来。
9、系统应具有一定的容错能力,对一些错误事件能进行自动补救。
13.6多线程
编写多线程程序,尽量使用VC提供的线程类。
凡是可能有多个线程访问的变量或者资源,一定要用临界区进行保护。
尽量不要用线程去访问界面,因为MFC的界面类都不是线程安全的。