收藏 分享(赏)

C&C++语言编程规范.doc

上传人:hwpkd79526 文档编号:6757719 上传时间:2019-04-22 格式:DOC 页数:28 大小:336.50KB
下载 相关 举报
C&C++语言编程规范.doc_第1页
第1页 / 共28页
C&C++语言编程规范.doc_第2页
第2页 / 共28页
C&C++语言编程规范.doc_第3页
第3页 / 共28页
C&C++语言编程规范.doc_第4页
第4页 / 共28页
C&C++语言编程规范.doc_第5页
第5页 / 共28页
点击查看更多>>
资源描述

1、C/C+语言编程规范文件标识: XXX当前版本:作 者:文件状态: 草稿 正在修改 正式发布 完成日期:XXXXXXhttp:/www.XXX.comC/C+语言编程规范 XXX 2010 Page 2 of 282I. 文档控制1) 文档更新记录日期 更新人 版本 备注2) 文档审核记录日期 审核人 职务 备注3) 文档发行范围分发单位 说明XXX XXX 2010 Page 3 of 28目录1.引言 51.1 编写目的 .51.2 内容 .51.3 预期读者 .51.4 参考资料 .51.4 缩写和术语 .52命名规则 .63文件组织 .83.1 头文件的结构 83.2 内部包含卫哨 8

2、3.3 源文件的结构 83.4 头文件包含顺序 93.5 外部包含卫哨 93.6 目录结构 103.7 其它原则 104代码版式 .114.1 空行 114.2 代码行 114.3 代码行内的空格 124.4 对齐与缩进 124.5 长行拆分 134.6 修饰符的位置 144.7 注释风格 145 编程规则和建议 .165.1 表达式 165.2 声明和定义 175.3 整数数据类型及操作 175.4 字符操作 185.5 浮点型 185.6 常量 195.7 指针 195.8 数组 205.9 函数 205.10 控制语句 215.11 内存使用 215.12 错误处理 215.13 断言

3、215.14 类 225.15 结构成员对齐方式 225.16 连接规范 245.17 函数调用规范 255.18 通用规则和建议 256附件 .276.1 头文件样式模板 27C/C+语言编程规范 XXX 2010 Page 4 of 2846.2 源文件样式模板 276.3 函数头注释模版 28XXX XXX 2010 Page 5 of 281.引言1.1 编写目的本文档的目的是为 XXX 公司使用 C/C+语言进行软件开发提供编程规范指南。声明:(1) 本规范针对的 C+语言是指 ISO/IEC 14882:1998 标准规定的 C+语言规范。(2) 本规范对编程过程中使用的第三方程序

4、库不做任何假设,第三方程序库仍然保留其固有的编程风格和规范。规则 0:不存在绝对的编程规范和规则;规范和规则不应有正确与错误之分,只有适合与不适合、好与不好或者通用与不通用的区别。规范和规则强调的是一致性,这个一致性有三层含义:每个开发人员编写的代码要前后一致;每个项目组采用统一的编程规范;全公司各项目组都采用统一的编程规范。1.2 内容编程规范不仅仅包含编程风格,更重要的是指导如何正确运用语言提供的机制,提供常用的惯用法,改善编程效率和程序性能的方法和技巧,以及编程的禁区。大部分的内容可以用“规则”或“规范”的形式固定下来,但是也有很多内容只能以“建议”的形式呈现。1.3 预期读者本文档的主

5、要读者包括:- 开发设计人员和程序员- 项目管理员- 软件质量保证人员1.4 参考资料1 2 3 4 1.5 缩写和术语标识符(identifier) 指 C/C+中的一个变量、常量、宏、函数或类型的名字定义(define) 提供一个程序元素或实体在程序中的唯一描述声明(declare ) 把一个名字引入一个程序或者一个作用域,以向编译器表明该名字的存在性及其作用域作用域(scope) 一个名字可以被引用的程序范围。C+有 6 种作用域:全局,文件,程序块,函数体,函数原型,类,名字空间编译单元 源文件及其递归包含的所有头文件共同编译生成的目标模块(.obj/.o),一个源文件是一个最小的编译

6、单元C/C+语言编程规范 XXX 2010 Page 6 of 2862命名规则类别 规则 示例共性规则- 所有标识符的名字应当直观且可以顺利拼读,可望文生义,不必进行解码(即自说明的,几乎不需要专门的注释) ;- 同一个作用域中不要出现仅靠大小写来区分的相似标识符,虽然 C/C+是大小写相关的;- 在设计中,所有模块(namespace)、函数、变量、宏、类型等的名称均由字母、数字和单下划线组成,尽量少使用数字(除非语义如此) ,标识符的头部和尾部一般不要使用下划线和数字;- 所有的名称均应具有实际含义,应体现实际用途,不应该包含那些不被普遍接受和认同的缩略语;- 尽量不要出现局部变量和全局

7、变量同名的现象,虽然两者作用域不同而不会发生语法错误,但是会使人误解并可能引起语义错误;- 变量的名字应该使用“名词+名词”或“形容词+名词”的格式来命名;- 函数名建议使用“动词”或“动词+名词”的格式来命名,并表明自己的功能;- 使用正确的反义词来命名具有相反意义的变量或相反动作的函数等;- 标识符的长度应该符合“min-length XXX XXX 2010 Page 7 of 28内部定义的 enum 代替;函数名(包括成员函数)- 全部使用首字母大写的单词组合而成;- 特别地,在特定的快速开发工具以及使用工具自动生成的代码,具有特定的命名规则,如果这些规则用户不可编辑修改,请遵循这些

8、特定的规则而不必拘泥于本文档的建议;get_name()compare_times()write_to_video_card()GetMaxSpeed()DeleteItem()宏和常量- 以所有字母全大写的单词和单下划线组成,以下划线作为区分语义各部分的分割符,首尾不使用下划线;- 特别地,标志宏可以在头部或尾部加_,常见的标志宏有:头文件包含卫哨、预编译组态、编译器和操作系统特征定义等;SERVER_PORT_NUMBERTIME_OUT_SUPPORT_NAMESPACE_SunCC_unix_linux_枚举类型常量 - 遵循常量的命名规则;enum ThreadStatusTHREA

9、D_INIT,THREAD_ACTIVE,THREAD_SUSPENDED,THREAD_DEAD;全局变量/对象- 如果不得已使用全局变量,则遵循普通变量的命名规则,同时加前缀 g_/gs_g_oldPositiongs_totalNumber说明:具体项目的模块命名、文件命名、类型系统定义等均由相应的项目管理文档定义,并由项目组全体成员共同遵守。C/C+语言编程规范 XXX 2010 Page 8 of 2883文件组织3.1 头文件的结构【注意】不要在头文件中包含文件作用域级的静态函数的原型声明和实现,以及文件作用域级的静态变量的声明和定义。3.2 内部包含卫哨内部包含卫哨实际上是一种标

10、志宏,其作用是防止同一个头文件的内容在同一个编译单元中被重复包含,因为如果重复包含了同一个头文件的内容,编译器就会报告重复定义错误。有了内部包含卫哨,我们就可以在同一个编译单元中多次包含同一个头文件而不会造成重复包含。例如:/ xxx.cpp#include “xxx.h”#include “xxx.h” / No problem!内部包含卫哨应该遵循下列命名规则:(1)基本命名应该与头文件名称一致,首尾下划线可选;示例:/ SwDTV_TIF_data.h#ifndef _SwDTV_TIF_DATA_H_#define _SwDTV_TIF_DATA_H_#endif / !_SwDTV_

11、TIF_DATA_H_(2)在基本名称的基础上可以在首尾添加修饰词,例如 INCLUDED 等;示例:/ SwDTV_TIF_data.h#ifndef _INCLUDED_SwDTV_TIF_DATA_H_#define _INCLUDED_SwDTV_TIF_DATA_H_#endif / !_INCLUDED_SwDTV_TIF_DATA_H_or:/ SwDTV_TIF_data.h#ifndef _SwDTV_TIF_DATA_H_INCLUDED_#define _SwDTV_TIF_DATA_H_INCLUDED_#endif / !_SwDTV_TIF_DATA_H_INCLU

12、DED_3.3 源文件的结构源文件应遵循以下顺序安排内部结构: 源文件注释(包括文件说明、功能描述、版权声明等) (必须有) 预处理指令(如果需要) 常量和宏定义(如果需要) 外部变量声明和全局变量定义及初始化(如果需要) 成员函数和全局函数的定义(如果需要) 文件修改记录源文件的样式模板请参考本文档 6.2 节。XXX XXX 2010 Page 9 of 283.4 头文件包含顺序无论是在头文件中还是源文件中,在文件开始部分包含其他的头文件时需要遵循一定的顺序。如果包含顺序不当,有可能出现包含顺序依赖问题,甚至引起编译时错误。推荐的顺序如下:在头文件中: 首先包含当前工程中所需要的自定义头

13、文件(顺序自定) ; 其次包含第三方程序库的头文件; 最后包含标准头文件;在源文件中: 首先包含该源文件对应的头文件(如果存在) ; 其次包含当前工程中所需要的自定义头文件; 然后包含第三方程序库的头文件; 最后包含标准头文件;3.5 外部包含卫哨当包含一个头文件的时候,如果能始终如一地使用外部包含卫哨,可以显著地提高编译速度,因为当一个头文件被一个源文件反复包含多次时(常常是因为递归的#include 指令展开后所致) ,可以避免多次查找和打开头文件的操作。例如:#if !defined (_ INCLUDED_P_THREAD_)#include “pthread.h”#define _

14、INCLUDED_P_THREAD_#endif / ! _ INCLUDED_P_THREAD_建议外部包含卫哨和内部包含卫哨一致起来,这样就可以少定义一个标志宏。例如:#if !defined (NST_THREAD_H_)#include “Utility/NST_thread.h”#endif / !NST_THREAD_H_因为文件 NST_thread.h 中的内部包含卫哨就是 NST_THREAD_H_。可以仅在头文件中包含其他头文件时使用外部包含卫哨,源文件中可以不使用,也基本不会影响编译速度。标准头文件的外部包含卫哨如下定义:#if !defined(_INCLUDED_ST

15、D_DEQUE_)#include #define _INCLUDED_STD_DEQUE_#endif / !_INCLUDED_STD_DEQUE_#if !defined(_INCLUDED_STD_CASSERT_)#include #define _INCLUDED_STD_CASSERT_#endif / !_INCLUDED_STD_CASSERT_#if !defined(_INCLUDED_STD_STRING_)#include #define _INCLUDED_STD_STRING_#endif / !_INCLUDED_STD_STRING_#if !defined(

16、_INCLUDED_WINDOWS_H_)C/C+语言编程规范 XXX 2010 Page 10 of 2810#include #define _INCLUDED_WINDOWS_H_#endif / !_INCLUDED_WINDOWS_H_标准头文件外部包含卫哨标志宏的定义规则如下:“_INCLUDED_STD_” + “大写头文件名”如果标准头文件带有.h 扩展名,则定义规则如下:“_INCLUDED_STD_” + “大写头文件名” + “_H_”3.6 目录结构 建议将头文件和源文件置于不同的目录下存放,这样便于配置管理和维护。例如可将头文件保存于 include 目录下,将源文件

17、保存于 source 目录下,都可以是多级目录; 其他文件可以遵循 MSVC 工程的惯例。3.7 其它原则 要隔离出依赖于机器硬件和操作系统的代码; 将软件包和模块的对外接口与其实现分离(接口指函数原型和抽象类等) ; 为每一个软件包和模块创建一个入口头文件,它#include 为使用该软件包或模块所必须包含的头文件。XXX XXX 2010 Page 11 of 284代码版式版式虽然不会影响程序的功能,但会影响可读性。程序的版式追求清晰、美观,是编程风格的重要构成因素。4.1 空行空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。建议在需要空行的地方仅使用 12

18、 个空行。 建议 4.1.1:在每个类声明之后、每个函数定义结束之后都要加空行。参见示例 4-1(a) ; 建议 4.1.2:在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。参见示例 4-1(b ) ; 加空行的原则:使得代码块儿看起来松紧有度。/ 空行void Function1()/ 空行void Function2()/ 空行void Function3()/ 空行while (condition)statement-block 1;/ 空行if (condition) statement-block 2;elsestatement-block 3;/ 空行sta

19、tement-block 4; 示例 4-1(a) 函数之间的空行 示例 4-1(b) 函数内部的空行4.2 代码行 规则 4.2.1:if、for、while、do 等语句自占一行,执行语句不得紧跟其后。示例 4-2(a)为风格良好的代码行,示例 4-2(b)为风格不良的代码行。int width; / 宽度int height; / 高度int depth; / 深度int width, height, depth; / 宽度高度深度x = a + b;y = c + d;z = e + f;X a + b; y = c + d; z = e + f;if (width =”、 “”、 “

20、.*”、 “-*”、 “:”这类操作符前后不加空格; 建议 4.3.8:象“?” 、 “:”这类操作符前后要加空格; 建议 4.3.9:对于表达式比较长的 for 语句和 if 语句,为了紧凑起见可以适当地去掉一些空格,如 for (i=0; i= 2000) / 良好的风格if(year=2000) / 不良的风格if (a=b) / 不要写成 b - Function();示例 4-3 代码行内的空格4.4 对齐与缩进 规则 4.4.1:程序块的分界符和 应独占一行并且位于同一列,同时与引用它们的语句左对齐或者向右缩进 4 个空格(可以设置编辑器使 TAB 键自动转换为 4 个空格) ;

21、规则 4.4.2: 之内的代码块与 左对齐(函数体除外) ,或者在右边 4 个空格处左对齐,不要使用 TAB 键; 对齐与缩进风格的原则:使代码看起来段落和层次分明。示例 4-4(a)为风格良好的对齐,示例 4-4(b)为风格不良的对齐。XXX XXX 2010 Page 13 of 28void Function(int x) / program codevoid Function(int x) / program codeif (condition) / program codeelse / program codeif (condition) / program codeelse / p

22、rogram codefor (initialization; condition; update) / program codefor (initialization; condition; update) / program codeWhile (condition) / program codewhile (condition) / program code如果出现嵌套的 ,则使用缩进对齐,如:示例 4-4(a) 风格良好的对齐与缩进 示例 4-4(b) 风格不良的对齐4.5 长行拆分 规则 4.5.1:代码行最大长度控制在一屏之内。代码行不要过长,否则眼睛看不过来,也不便于打印; 规则

23、 4.5.2:长表达式要在低优先级操作符处拆分成多行,操作符放在新行之首(以便突出操作符) 。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。这样的运算符最常见的就是二元运算符和输入输出运算符; 对于像 if、for、while 等语句块儿,如果条件表达式需要拆分成多行,为了避免下面的语句块看起来被条件表达式的缩进所架空,可以适当缩进下面的语句块。if ( (very_longer_variable1 = very_longer_variable12)idx2 = max min;left = 1 idx2) right = idx3+;if (right = limit) . . .XX

24、X XXX 2010 Page 17 of 28 建议 5.1.3:在 if、for 和 while 语句中要使用逻辑或关系表达式作为控制表达式。如果该表达式不是逻辑表达式,就使用显式验证。反例:表达式隐式验证while (a + b) 范例:表达式显式验证while (a + b) != 0) 建议 5.1.4:在写 if 语句的条件表达式时,如果是变量和常量的比较关系,最好将常量放在前面。这样做的好处在于:如果您忘记了一个=号,编译器会提示您,因为你不能给常量赋值。范例:if (FILE_NOT_FOUND = errno) 建议 5.1.5:尽量避免表达式中混合使用有符号数和无符号数。当

25、有符号数和无符号数混合运算时,有符号数有可能转变为无符号数。如果有符号数是个负数,转换后可能变为正数,这会导致不可预料的结果。 建议 5.1.6:避免逻辑表达式的结果为恒真或恒假。这样的判断往往是毫无意义的,有时也是潜在的 bug,不能到达程序的某些部分。 建议 5.1.7:在使用运算符if (abs(x y) :epsilon()/ x = yXXX XXX 2010 Page 19 of 28else/ x != yif (abs(x) :epsilon()/ x = 0else/ x != 0虽然不建议直接使用=和!=比较浮点数,但是可以直接比较浮点数的大小,即可将直接应用于浮点数之间的

26、比较及浮点数和整数的比较。但是,对内置类型来说, “!(ab) 建议 5.9.6: 为多个构造函数设计一个统一的私有_Init()函数。为多个构造函数设计一个统一的私有_Init()函数来初始化所有的类数据成员,这样的话我们XXX XXX 2010 Page 21 of 28就不会在增加或减少数据成员时忘记修改某个构造函数。 建议 5.9.7: 只有在必要时才使用内联函数(inline functions) 。 建议 5.9.8: 对于用户自定义数据类型的输入参数,应该把“值传递”改为“const i _QueueLocker;CyclicQueue();CyclicQueue();bool

27、push(const XYZbool pop(XYZprivate:XYZ *m_pBuffer_;volatile size_type m_popPos;volatile size_type m_count;CriticalSection m_mutex;#pragma pack(pop)#endif / !_INCLUDED_INTERFACE_H_5.16 连接规范在使用不同编程语言进行软件联合开发的时候,需要统一函数、变量、数据类型、常量等的连接规范,特别是在不同模块之间共享的接口部分。当开发程序库的时候,明确连接规范也是必须要遵循C/C+语言编程规范 XXX 2010 Page 24

28、 of 2824的一条规则。对 COM 接口(Interface )及其使用的数据类型来说,是否采用统一的连接规范,对其二进制兼容性和可移植性都没有影响。因为即使接口两端(COM 接口实现端和客户端)对接口本身的解释不同(连接规范主要影响到名字改编方案的不同) ,但是只要它们使用一致的成员对齐方式和布局方案、一致的调用规范、一致的 virtual function 实现方式,总之就是一致的 C+对象模型,并且保证 COM 组件升级时不改变原来的接口和数据类型定义,则所有方法(methods,这里指 Interface 中的 pure virtual functions)的运行时绑定都不会存在问

29、题(所有方法的调用都被转换为通过对象指针对 vptr 和 vtable及函数指针的操作,这种间接性不再需要任何方法名即函数名的参与,而接口名和方法名只是为了让客户端的代码能够顺利通过编译,但是连接时就全部不再需要了) 。但是对于定义于普通静态连接库和动态连接库中的全局数据类型、全局函数、全局变量甚至全局常量,它们的连接规范必须在两端保持一致,否则会出现连接问题(linking error: unresolved external symbol 等) 。因此需要在它们的前面或者两端指定连接规范。通用的连接规范莫属 C 连接规范:extern “C”。具体使用方法如下:(1)如果是仅对一个类型、函

30、数、变量或常量限定连接规范:extern “C“ void WinMainCRTStartup();extern “C“ const CLSID CLSID_DataConvert;extern “C“ struct Student;extern “C“ Student g_Student;(2)如果是对一段代码限定连接规范:#ifdef _cplusplusextern “C“ #endifconst int MAX_AGE = 200;#pragma pack(push, 4)typedef struct _Personchar *m_Name;int m_Age; Person, *Pe

31、rsonPtr;#pragma pack(pop)Person g_Me;int _cdecl memcmp (const void *, const void *, size_t);void * _cdecl memcpy (void *, const void *, size_t);void * _cdecl memset (void *, int, size_t);#ifdef _cplusplus#endifXXX XXX 2010 Page 25 of 285.17 函数调用规范模块逻辑接口上每一个函数的调用规范(调用约定)也必须一致,因为调用规范会影响到函数参数的压栈顺序和退栈责任

32、,这同样需要显式地在函数的原型和实现处指定,如果不指定也会出现编译连接错误,甚至运行时错误。如果为某一个函数指定了调用规范,它将覆盖为整个工程指定的调用规范,即其优先级高于工程设置;否则将默认使用工程设定的调用规范,为整个工程设定的调用规范将影响所有的函数,除非函数已经特别指定了调用规范。Win32 平台下可使用的调用规范有:(1)_stdcall:常用于标准 API 函数、静态函数、COM 接口方法;(2)_cdecl:普通 C/C+函数常用的调用规范,也是 C/C+默认的调用规范;(3)_fastcall:快速调用规范;(4)thiscall: C+非静态成员函数默认调用规范(该规范不需要

33、显式指定,因为它并不是一个程序员可以使用的关键字,而是编译器默认采用的) 。它们的使用方法请参考 MSDN。声明举例如下:void _fastcall PrintPerson(const Person *p);bool _stdcall ComparePerson(const Person *left, const Person *right);int _cdecl memcmp (const void *p, const void *q, size_t);void* _cdecl memcpy (void *, const void *, size_t);void* _cdecl memse

34、t (void *, int, size_t);应该强调的是:凡是接口函数都必须显式地指定其调用规范,除非接口函数是类的非静态成员函数;如果不特别指定,类的的静态成员函数和全局函数都采用 C/C+默认的函数调用规范或者由工程设置指定的调用规范(注意:类的静态成员函数的默认调用规范不是 thiscall,类的友元函数的调用规范也不是 thiscall,而是由函数本身指定或者由工程设定) ,因此最好也为静态成员函数特别指定调用规范。特别地,在 COM 接口中,接口方法也必须按照规范指定_stdcall 调用规范。5.18 通用规则和建议 规则 5.18.1:编译时将编译警告级别设置为最高级并尽量消

35、除所有警告; 规则 5.18.2:不得定义递归的宏,因为这样没有效果,C+预处理器不会执行递归展开; 建议 5.18.1:尽量避免使用宏定义,如用宏定义字符串、数字、代码段等;在 C+中使用宏来定义代码段具有一定的风险:(1)由宏控制引起的语法错误和运算优先级错误很难隔离出来;(2)宏不遵守作用域规则;(3)宏会增加检查副作用的难度;(4)宏可能产生奇异语法和错误结果而编译器检查不出来;(5)宏不可调试;由于这些原因,导致安全的宏定义的编写需要更多的精力和经验。虽然宏有诸多缺点,但是并非所有的宏都能用内联函数来替代。对于一些特殊应用,没有替代预处理宏的方便的方式(如用于条件编译的#if,#if

36、def#endif 结构、名字拼接#和串化符号#等) 。但是经过精心设计的精巧的宏代码结构,却可以节省大量的重复代码书写量,提高编程效率,而且使用也很方便。典型的例子如 MFC 类库中的消息处理机制所使用的大量的宏; 建议 5.18.2:使头文件之间在编译、连接时相互依赖性最小。这可以通过使用前置声明等方法来解决; 建议 5.18.3:在头文件中使用外部包含卫哨(冗余包含卫哨)来包含其他头文件,以提高编译速度;C/C+语言编程规范 XXX 2010 Page 26 of 2826 建议 5.18.4:一个文件(头文件或源文件)如果要使用另一个头文件中定义或声明的元素,请直接包含该头文件,不要试

37、图通过第三个头文件间接包含之; 建议 5.18.5:使用 STL 和泛型算法来取代手工制作的数据结构和算法。XXX XXX 2010 Page 27 of 286附件6.1 头文件样式模板/* Copyright (c) 2004-2008 Software Technology.* All rights reserved.* File Type : C+ Header File(*.h)* File Name : * Module : * Create on : YYYY/mm/dd* Author : Your Name* Description about this header fil

38、e*/#ifndef XXX_H_#define XXX_H_头文件的实际内容#endif / XXX_H_/* $log$* Revision 1.1 YYYY/mm/dd hh:mm:ss Somebody* Description about this revision*/6.2 源文件样式模板/* Copyright (c) 2004-2008 Software Technology.* All rights reserved.* File Type : C+ Source File(*.cpp)* File Name : * Module : * Create on : YYYY/m

39、m/dd* Author : Your Name* Description about this source file*/C/C+语言编程规范 XXX 2010 Page 28 of 2828源文件的实际内容/* $log$* Revision 1.1 YYYY/mm/dd hh:mm:ss Somebody* Description about this revision*/6.3 函数头注释模版/* Descriptions.* param name1 : in/outDescriptions* param name2 : in/outDescriptions* param name3 : in/outDescriptions* return Descriptions* exception Type1: Descriptions* exception Type2: Descriptions* exception Type3: Descriptions*/

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报