《2022年编程规范 .pdf》由会员分享,可在线阅读,更多相关《2022年编程规范 .pdf(16页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月1编程规范清华大学计算机系网络所版权所有不得复制名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月21. 说明本编程规范使用在清华大学计算机系网络研究所CNPT 实验室承担的863 重点项目IPTEST 中。本文档的目的在于保证测试仪软件编写的质量,以避免在开发和调试过程中出现不必要的麻
2、烦。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月32. 文件头的编写规范每个文件开头部分都应当包括:文件标题(Title ) ;版权说明(Copyright ) ;修改记录(Modification History ) 。(1)Title 中包括文件的名称和文件的简单说明。Title 应该在一行内完成。(2)Copyright 包括一个版权说明,长度为
3、一行。例如,在本项目中,版权说明使用:/* Copyright (c) 2000 by Tsinghua Univ., Beijing, P.R.C. */ ( 3)Modification History 记录文件修改的过程,只记录最主要的修改。当书写新的函数模块时,只需要使用形如 “ add func1()”这样的说明;如果后面又对函数中的算法进行了修改,需要指出修改的具体位置和修改方法。Modification History的具体格式为:, 如:19apr2000,by Mike, added routines myfunc() 一个文件头的具体范例如下:/* fooLib.c - f
4、oo subroutine library */ /* Copyright (c) 2000 by Tsinghua Univ., Beijing, P.R.C. */ /* modification history - 15sep1999, by nfs, added defines MAX_FOOS and MIN_FATS. 15feb2000, by dnw,added routines fooGet() and fooPut(); added check for invalid index in fooFind(). 10feb2000, by dnw,written. */ 名师资
5、料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月43. C 代码书写规范C 程序的书写范例:见fooLib.c 3.1 C Module Layout C Module Layout 包括以下内容:(1)General Module Documentation :对整个模块目的和功能的完整描述注释。内部包括DESCRIPTION和 INCLUDE FILES两部
6、分。 INCLUDE FILES后列出所包含的头文件。(2)Includes:包含的头文件说明。(3)Typedefs:类型定义。(4)Globals:全局变量定义。只有那些可以在本模块外访问的变量才定义为全局变量。(5)Locals:局部变量定义。那些只希望在本模块内访问的变量定义为局部变量。(6)Forward Declarations :声明将在本模块内使用,而且在本模块中实现的函数。一个具体的范例如下:/* fooLib.c - foo subroutine library */ /* Copyright (c) 2000 by Tsinghua Univ., Beijing, P.R
7、.C. */ /* modification history - 15sep1999, by Mike, added defines MAX_FOOS and MIN_FATS. 15feb2000, by Tom, added routines fooGet() and fooPut(); added check for invalid index in fooFind(). 10feb2000, by John, written. */ /* DESCRIPTION This module is an example of the Wind River Systems C coding c
8、onventions. . INCLUDE FILES: fooLib.h */ /* includes */ #include fooLib.h /* defines */ #define MAX_FOOS 112 /* max # of foo entries */ #define MIN_FATS 2 /* min # of FAT copies */ /* typedefs */ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 16 页 - - - - - - -
9、 - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月5typedef struct fooMsg /* FOO_MSG */ VOIDFUNCPTR func; /* pointer to function to invoke */ int arg FOO_MAX_ARGS; /* args for function */ FOO_MSG; /* globals */ char * pGlobalFoo; /* global foo table */ /* locals */ LOCAL int numFoosLost; /* count of foos lost
10、 */ /* forward declarations */ LOCAL int fooMat (list * aList, int fooBar, BOOL doFoo); FOO_MSG fooNext (void); S TAT US fooPut (FOO_MSG inPar); 3.2 C Subroutine Layout C Subroutine Layout 主要包括:(1)Banner:形式为 /* (2)Title:由 routine name 和一个简单的描述组成。(3)Description:对 routine 的完整描述,主要包括routine 的功能和使用方法。(4
11、)Returns:routine 的返回值描述。如果 routine 的返回类型为void,则使用如下的说明:RETURNS: N/A (5)Error Number :在 ERROR 标识后,列出所有可能由routine 产生的错误值。C Subroutine Layout 的一个简单范例如下:/* * * fooGet - get an element from a foo * * This routine finds the element of a specified index in a specified * foo. The value of the element found
12、is copied to . * * RETURNS: OK, or ERROR if the element is not found. * * ERRNO: * S_fooLib_BLAH * S_fooLib_GRONK */ STATUS fooGet 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月6( FOO foo, /* foo in wh
13、ich to find element */ int index, /* element to be found in foo */ int * pValue /* where to put value */ ) . 3.3 C Declaration Formats (1)对于基本数据类型,声明在一行内完成。如:unsigned rootMemNBytes; /* memory for TCB and root stack */ int rootTaskId; /* root task ID */ BOOL roundRobinOn; /* boolean for round-robin m
14、ode */ (2)指针定义中 * 靠近变量。如:FOO_NODE *pFooNode; /* foo node pointer */ FOO_NODE *ppFooNode; /* pointer to the foo node pointer */ (3)在结构定义时,一律使用typedef 关键字。在 struct 后面的名字,其命名规范如3.5(1);结构名一律使用大写字母,单词之间间用 _ 隔开。如果在结构定义内部要定义其他结构,使用该结构的大写名(即不包括 struct 关键字,见下面的例子)。如:typedef struct symtab /* SYMTAB - symbol t
15、able */ OBJ_CORE objCore; /* object maintanance */ HASH_ID nameHashId; /* hash table for names */ SEMAPHORE symMutex; /* symbol table mutual exclusion sem */ PART_ID symPartId; /* memory partition id for symbols */ BOOL sameNameOk; /* symbol table name clash policy */ int nSymbols; /* current number
16、 of symbols in table */ SYMTAB; 当结构定义内部使用其他结构的指针时,不使用该结构的大写名定义,而使用 struct关键字。如:使用如下的方式定义:typedef struct tcbInfo struct fooInfo * pfooInfo; . TCB_INFO; 而不使用如下的方式:typedef struct tcbInfo FOO_INFO * pfooInfo; . TCB_INFO; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页
17、,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月7(3)函数头的写法见如下例子int lstFind ( LIST *pList, /* list in which to search */ NODE *pNode /* pointer to node to search for */ ) 每个参数分行书写,后面紧跟参数的注释说明。如果函数没有输入参数,使用如下的写法:STATUS fppProbe (void) 3.4 C Code Layout (1)缩进大小为4 个字符。(2)当使用 和 时,使用如下的格式:if
18、 ( condition ) statements else statements 即 由下一行开头开始。(3)在书写注释时,使用以下三种方式之一: 单行注释/* This is the correct format for a single-line comment */ 多行注释/* * This is the correct format for a multiline comment * in a section of code. */ 紧跟在代码和声明之后的注释int foo ( int a, /* this is the correct format for a */ /* mul
19、tiline comment in a declaration */ BOOL b /* standard comment at the end of a line */ ) day = night; /* when necessary, a comment about a line */ /* of code can be done this way */ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 16 页 - - - - - - - - - 编程规范 清华大学计
20、算机系网络研究所CNPT Lab 2001年 1 月83.5 C 命名规范(1)变量名、函数名、结构名中首单词小写,后面的其他单词首字母大写。如:aVariableName (2)如果规则( 1)中用到单词全部大写的情况,单词之间使用 _ 分隔。(这条规则在定义结构时尤其重要)如:A_CONSTANT_VALUE (3)每个模块定义中应该包含一个长度为2 5 个字母的前缀, 在后面的定义中都使用这样的前缀。如:fooLib.c module name fooObjFind subroutine name fooCount variable name FOO_MAX_COUNT constant
21、 FOO_NODE type (4)命名中使用module-noun-verb 规则,即首先为模块前缀,其次是名词,最后是动词。如:fooObjFind foo - object - find sysNvRamGet system - NVRAM - get taskSwitchHookAdd task - switch hook - add (5)在头文件的预处理符号中使用如下例子中的格式:对于 fooLib.h 使用: _FOOLIB_H 这样的形式(6)在 n 层指针变量的前使用n 个 p 。如:FOO_NODE *pFooNode; FOO_NODE *ppFooNode; FOO_N
22、ODE *pppFooNode; (7)文件名的命名规则和变量相同。文件名的后缀使用小写字母。3.6 C Style (1)注释:程序代码中必须包含足够多的注释。(2)C 程序应该限制规模,函数大小50-500 行之间, C 文件大小在200-2000 行之间。(3)数值常数:在使用常数时,尽量使用宏进行定义。(4)在进行布尔表达式判断时,当进行数值的判断时,一律使用如下的形式:if (x = 0) 而不使用:if ( !x) 当进行布尔变量的判断时,使用如下的形式:if (libInstalled) 而不使用:if (libInstalled = TRUE) (5)模块内部使用的模块和变量,
23、不要在提供给用户的头文件中出现。(6)在传递和返回结构时,一律使用结构指针。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月9(7)函数在返回状态信息时,使用OK 或者 ERROR。没有任何返回值时,应在函数末尾返回 void。(8)函数末尾使用return 时,对于返回的内容一律加括号。如:return(OK); (9)用户可以使用的一些宏定义: TRU
24、E 和 FALSE:用于布尔类型数据 EOS:end-of-string ,即 0 NULL :空指针 LOCAL :即 static,在定义局部变量时使用(10) 在使用循环时,如果循环体为空,则使用空语句。如:for ( j = 0; j 100; j+); 应该写为:for ( j = 0; j 65535 #endif 如果 UNIX_MAX没有定义,编译器也不会报错。最好在前面加入判断:ifndef UNIX_MAX #endif 3.7 C Header File Layout 在头文件中,需要包括以下部分:(1) ifndef 文件名的大写。如:#ifndef _TYPES _H
25、 #define _TYPES_H #endif /* _TYPES_H*/ (2) 对 C+的支持,即#ifdef _cplusplus extern C #endif /* _cplusplus */ #ifdef _cplusplus #endif /* _cplusplus */ (4)声明。头文件中的声明推荐使用如下的顺序: 对其他头文件的包含 宏定义 类型定义名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 16 页 - - - - - - - - - 编程规范
26、 清华大学计算机系网络研究所CNPT Lab 2001年 1 月10 函数原型定义函数原型定义中的参数一律使用STDC 的风格,即如下面的形式:extern void bootParamsShow (char *paramString); 头文件中的函数原型不需要写注释,一般函数原型声明应该在一行内完成。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月1
27、14. 调试规范4.1 总的调试规范(1)程序中应该包括足够的调试信息。调试信息一律包含在ifdef _DEBUG #endif 内。(2)在函数入口处,推荐使用Assert() 对于参数的有效性进行判断。对于入口参数是指针的,必须使用Assert()进行判断。 Assert() 的使用方法为:Assert();assert()的具体使用方法请参考assert.h(在/h目录下 )中的定义。(也可以看 Unix 中的帮助文件)(3) 在代码中易出现问题的地方,也应该使用assert() 、或者其他的机制进行相应的检测。4.2 调试开关的书写(1)各模块根据需要可以定义一个或多个调试开关的宏:
28、总调试开关的宏命名格式: 模块缩写 _DEBUG 例: #define OSPF_DEBUG 0 注: 适用于该模块只使用一个总的调试开关的情况 专用调试开关的宏命名格式: 模块缩写 _功能 _DEBUG 例: #define OSPF_TIMER_DEBUG 1 注: 适用于该模块除了使用一个总的调试开关之外,还需另外使用几个的专用调试开关的情况 : (2)各模块的调试宏需要定义在一个调试头文件里: 模块的调试头文件命名格式: 模块缩写 Debug.h 例: ospfDebug.h, pppDebug.h 等等(3)调试信息宏开关的取值只能是0 或 1, 0 表示关闭调试信息, 1 表示打印
29、调试信息. 例: #define OSPF_TIMER_DEBUG 1 (4)使用调试宏开关时, 只使用 #if, 不用 #ifdef 或#ifndef( 后两种专用于表示功能选项开关) 例: #if OSPF_TIMER_DEBUG printf( %sOSPF_Timer: xxx timeout=%dn, DBG_WARNING, myTimer); #endif (5)调试信息类型名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 16 页 - - - - - -
30、- - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月12#define DBG_CRIT /* critical conditions */ #define DBG_ERROR /* error conditions */ #define DBG_WARNING /* warning conditions */ #define DBG_INFO /* informational */ (6)调试信息的打印格式: printf(%s 所在函数名 : 调试信息 n, 调试信息类型, 调试参数 .); 例: int OSPF_Timer(int aTimer, cha
31、r *p) #if OSPF_TIMER_DEBUG printf( %sOSPF_Timer: xxx timeout=%dn, DBG_WARNING, aTimer); #endif . (7)调试信息与assert(): 调试信息只用于程序中允许出现的情况, 如 malloc 返回 NULL 的情况,又如程序某一功能尚未支持的情况。assert用于程序中不允许出现的错误情况,即隐含着程序的其它部分必定有误操作而导致在此处出错的情况。4.3 调试记录调试属于软件开发工作的一部分,调试记录是软件产品的一个重要组成部分。在软件的调试过程中,要做好调试记录,以便于软件的后续开发和维护工作。由于
32、我们目前没有将编码工作和测试工作,所以调试的文档包括两个内容:(1)对软件的调试记录,即发现软件中的Bug 并进行修改的记录。由于在软件编码过程中的修改很频繁,对每个发现的问题都记录下来是不现实的。在我们的项目实施中,大家自己来决定什么东西需要记录下来。这种记录按照日期排序,基本的格式如下:(日期)如: 2000 年 6 月 26 日 (问题编号)如: 1 (问题征兆)如:发现缓冲中的报文被无端修改 (问题根源及解决方法)如:由于在多任务环境中对共享资源没有使用互斥机制,对于缓冲增加一个信号量进行保护(修改位于buffer.c 中) 由于在我们的代码文件中有修改记录,在进行回顾时,就很容易检索
33、到原来的修改原因和修改位置。(2)对软件的测试记录在我们编写代码过程中,经常需要对实现的子模块进行测试,尤其是对提供给他人使用的模块,必须进行测试,这时需要花费一定的工作量,编写测试代码。这部分测试代码是有价值的,所以同样需要一定的管理机制。在测试方面,这里作两点规定: 对于测试代码,要注意保存,并适当使用文档加以说明。文档中应该说明测名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNP
34、T Lab 2001年 1 月13试代码的测试目的。如果测试代码和文档分别存放,还需要在文档中对测试代码的保存位置加以说明。 对于测试结果要加以记录。例如:对某个模块的若干接口加以测试,要记录测试的目的、具体的测试方法和测试的结果(如:通过测试,或测试失败)。这样,如果模块出现问题,可以避免重复的测试工作。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月
35、145. 基本的数据定义在具体的编码中,请保持基本的数据定义的一致性。遇到需要共同使用的数据结构,需要协商定义。以下为几类必须在全部软件中保持一致的数据定义:(1) 整数: 8 位、 16 位、 32 位、 64 位,有符号、无符号的定义为:8 位:int8_t uint8_t 16 位:int16_t uint16_t 32 位:int32_t uint32_t 64 位:int64_t uint64_t 以上这种定义方法十分清晰,不要使用int、short、long 这样的定义。(2) 长度参数当函数接口涉及传递参数的长度时,推荐使用size_t 作为长度的类型。名师资料总结 - - -精
36、品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月156. 项目的管理方法(1) 程序完成采用提交的方式。整个项目代码部分使用CVS 进行管理。当某功能模块完成编程后,使用软件管理工具提交。在进行提交之前,必须对新加入的功能进行一定的测试,在尽量保证正确性后在进行提交。(2) 每次提交,必须在提交报告中写明新加入功能的内容、修改的文件范围等内容。(3) 对于外部可以使用的函数接口,
37、必须定义相关的头文件说明,并建立相关的详细说明文档;引用外部实现的函数,要在C 程序中包含相关函数接口定义的头文件。(4) 在进行详细的编码前,首先要将使用的数据结构和函数接口定义好。在将以上这些问题考虑清楚后,在进行函数内部实现的编码。(5) 如果涉及使用基本的数据结构(即预测到该数据结构将由多个模块共用),请首先将结构明确定义,写成头文件,提交讨论。之后在进行函数内部实现的编程,以保持代码的一致性。(6) 对于功能独立的模块应该建立单独的目录。独立使用(即其中定义的内容只在本模块中使用)的头文件放在自己的目录(/project/mymodule )下,公用的头文件放在总的头文件目录(如:/
38、project/h )下。(7) 各模块独立编写Makefile ,提供给外部使用的函数应该以库(即二进制代码)和头文件的形式出现。各函数应该提供相应的测试程序,测试程序不提交到CVS 的总备份中,但是应当独立保存,以备后面进一步的测试。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 16 页 - - - - - - - - - 编程规范 清华大学计算机系网络研究所CNPT Lab 2001年 1 月167. 代码的版本管理代码使用CVS 提供的命令进行版本的管理。在某
39、个模块(即我们这里的项目)达到一个阶段后,使用CVS 的 tag 命令对版本进行标记。标记名称统一为“rel-num1-num2” ,其中num1 为主版本号,num2 为从版本号, rel代表 release ,中间以“ -”连接。主版本号从1 开始,从版本号从0 开始。版本号应当连续使用。进行标记的操作时要小心,尤其不要删除以前标记的版本号。每次进行版本标记后,应当使用CVS 的 checkout 命令从服务器获得该版本,压缩后备份至服务器项目目录中“代码备份”目录中,并在该目录下的版本说明中增加备份记录。备份的文件名应当为“项目名-主版本号 -从版本号 .zip” 。备份记录中应当写明备份版本名称(包括项目名和版本号)、 备份日期、备份文件名、备份说明(说明版本的特征和主要修改)。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 16 页 - - - - - - - - -
限制150内