华为技术有限公司c语言编程规范.pdf

上传人:wj 文档编号:3437975 上传时间:2023-05-05 格式:PDF 页数:61 大小:915.01KB
下载 相关 举报
华为技术有限公司c语言编程规范.pdf_第1页
第1页 / 共61页
华为技术有限公司c语言编程规范.pdf_第2页
第2页 / 共61页
华为技术有限公司c语言编程规范.pdf_第3页
第3页 / 共61页
华为技术有限公司c语言编程规范.pdf_第4页
第4页 / 共61页
华为技术有限公司c语言编程规范.pdf_第5页
第5页 / 共61页
华为技术有限公司c语言编程规范.pdf_第6页
第6页 / 共61页
华为技术有限公司c语言编程规范.pdf_第7页
第7页 / 共61页
华为技术有限公司c语言编程规范.pdf_第8页
第8页 / 共61页
华为技术有限公司c语言编程规范.pdf_第9页
第9页 / 共61页
华为技术有限公司c语言编程规范.pdf_第10页
第10页 / 共61页
华为技术有限公司c语言编程规范.pdf_第11页
第11页 / 共61页
华为技术有限公司c语言编程规范.pdf_第12页
第12页 / 共61页
华为技术有限公司c语言编程规范.pdf_第13页
第13页 / 共61页
华为技术有限公司c语言编程规范.pdf_第14页
第14页 / 共61页
华为技术有限公司c语言编程规范.pdf_第15页
第15页 / 共61页
华为技术有限公司c语言编程规范.pdf_第16页
第16页 / 共61页
华为技术有限公司c语言编程规范.pdf_第17页
第17页 / 共61页
华为技术有限公司c语言编程规范.pdf_第18页
第18页 / 共61页
华为技术有限公司c语言编程规范.pdf_第19页
第19页 / 共61页
华为技术有限公司c语言编程规范.pdf_第20页
第20页 / 共61页
亲,该文档总共61页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

华为技术有限公司c语言编程规范.pdf

《华为技术有限公司c语言编程规范.pdf》由会员分享,可在线阅读,更多相关《华为技术有限公司c语言编程规范.pdf(61页珍藏版)》请在冰点文库上搜索。

华为技术有限公司c语言编程规范.pdf

DKBA华为技术有限公司内部技术规范DKBA2826-2011.5C语言编程规范2011年5月9日发布2011年5月9日实施华为技术有限公司HuaweiTechnologiesCo.,Ltd.版权所有侵权必究Allrightsreserved密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第2页,共61页Page2,Total61修订声明Revisiondeclaration本本规范规范拟制与解释部门:

拟制与解释部门:

本规范的相关系列规范或文件:

相关国际规范或文件一致性:

替代或作废的其它规范或文件:

相关规范或文件的相互关系:

规范号规范号主要起草部门专家主要起草部门专家主要评审部门专家主要评审部门专家修订情况修订情况DKBAxxxx.x-xxxx.xxPSST质量部:

郭曙光00121837网络:

张伟00118807周灿00056781王晶00041937陈艺彪00036913IP开发部:

薛治00038309核心网:

张小林00058208王德喜00040674李明胜00042021软件公司:

文滔00119601无线:

刘爱华00162172中研:

谭洪00162654PSST质量部:

李重霄00117374郭永生00120218核心网:

张进柏00120359中研:

张建保00116237无线:

苏光牛00118740郑铭00118617陶永祥00120482软件公司:

周代兵00120359刘心红00118478朱文琦00172539网络:

王玎00168059黄维东49827IP开发部:

饶远00152313密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第3页,共61页Page3,Total61目录TableofContents0规范制订说明.50.1前言.50.2代码总体原则.50.3规范实施、解释.60.4术语定义.61头文件.62函数.123标识符命名与定义.213.1通用命名规则.213.2文件命名规则.233.3变量命名规则.233.4函数命名规则.243.5宏的命名规则.244变量.255宏、常量.286质量保证.327程序效率.368注释.399排版与格式.4410表达式.4611代码编辑、编译.4912可测性.5013安全性.5113.1字符串操作安全.5113.2整数安全.5213.3格式化输出安全.5613.4文件I/O安全.5713.5其它.5914单元测试.5915可移植性.6016业界编程规范.60密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第4页,共61页Page4,Total61C语言编程规范范范围围:

本规范适用于公司内使用C语言编码的所有软件。

本规范自发布之日起生效,以后新编写的和修改的代码应遵守本规范。

简简介:

介:

本规范制定了编写C语言程序的基本原则、规则和建议。

从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第5页,共61页Page5,Total6100规范制订说明规范制订说明0.1前言为提高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可测试、高效、可移植的代码,编程规范修订工作组分析、总结了我司的各种典型编码问题,并参考了业界编程规范近年来的成果,重新对我司1999年版编程规范进行了梳理、优化、刷新,编写了本规范。

本规范将分为完整版和精简版,完整版将包括更多的样例、规范的解释以及参考材料(what&why),而精简版将只包含规则部分(what)以便查阅。

在本规范的最后,列出了一些业界比较优秀的编程规范,作为延伸阅读参考材料。

0.2代码总体原则11、清晰第一、清晰第一清晰性是易于维护、易于重构的程序必需具备的特征。

清晰性是易于维护、易于重构的程序必需具备的特征。

代码首先是给人读的,好的代码应当可以像文章一样发声朗诵出来。

目前软件维护期成本占整个生命周期成本的40%90%。

根据业界经验,维护期变更代码的成本,小型系统是开发期的5倍,大型系统(100万行代码以上)可以达到100倍。

业界的调查指出,开发组平均大约一半的人力用于弥补过去的错误,而不是添加新的功能来帮助公司提高竞争力。

“程序必须为阅读它的人而编写,只是顺便用于机器执行。

”HaroldAbelson和GeraldJaySussman“编写程序应该以人为本,计算机第二。

”SteveMcConnell本规范通过后文中的原则(如头优秀的代码可以自我解释,不通过注释即可轻易读懂/头文件中适合放置接口的声明,不适合放置实现/除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音)、规则(如防止局部变量与全局变量同名)等说明清晰的重要性。

一般情况下,代码的可阅读性高于性能,只有确定性能是瓶颈时,才应该主动优化。

22、简洁为美、简洁为美简洁就是易于理解并且易于实现。

简洁就是易于理解并且易于实现。

代码越长越难以看懂,也就越容易在修改时引入错误。

写的代码越多,意味着出错的地方越多,也就意味着代码的可靠性越低。

因此,我们提倡大家通过编写简洁明了的代码来提升代码可靠性。

废弃的代码(没有被调用的函数和全局变量)要及时清除,重复代码应该尽可能提炼成函数。

本规范通过后文中的原则(如文件应当职责单一/一个函数仅完成一件功能)、规则(重复代码应该尽可能提炼成函数/避免函数过长,新增函数不超过50行)等说明简洁的重要性。

33、选择合适的风格,与代码原有风格保持一致、选择合适的风格,与代码原有风格保持一致产品所有人共同分享同一种风格所带来的好处,远远超出为了统一而付出的代价。

在公司已有编码规范的指导下,审慎地编排代码以使代码尽可能清晰,是一项非常重要的技能。

如果重构如果重构/修改其他风格修改其他风格的代码时,比较明智的做法是根据的代码时,比较明智的做法是根据现有现有代码代码的的现有风格继续编写代码现有风格继续编写代码,或者使用格式转换工具进行转密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第6页,共61页Page6,Total61换成公司内部风格。

0.3规范实施、解释本规范制定了编写C语言程序的基本原则、规则和建议。

本规范适用于公司内使用C语言编码的所有软件。

本规范自发布之日起生效,对以后新编写的和修改的代码应遵守本规范。

本规范由质量体系发布和维护。

实施中遇到问题,可以到论坛http:

/术语定义原则原则:

编程时必须坚持的指导思想。

规则规则:

编程时强制必须遵守的约定。

建议建议:

编程时必须加以考虑的约定。

说明说明:

对此原则/规则/建议进行必要的解释。

示例示例:

对此原则/规则/建议从正、反两个方面给出例子。

延伸阅读材料延伸阅读材料:

建议进一步阅读的参考材料。

11头文件头文件背景对于对于C语言来说,头文件的设计体现了大部分的系统设计。

语言来说,头文件的设计体现了大部分的系统设计。

不合理的头文件布局是编译时间过长的根因,不合理的头文件实际上不合理的设计。

术语定义:

依赖依赖:

本章节特指编译依赖。

若x.h包含了y.h,则称作x依赖y。

依赖关系会进行传导,如x.h包含y.h,而y.h又包含了z.h,则x通过y依赖了z。

依赖将导致编译时间的上升。

虽然依赖是不可避免的,也是必须的,但是不良的设计会导致整个系统的依赖关系无比复杂,使得任意一个文件的修改都要重新编译整个系统,导致编译时间巨幅上升。

在一个设计良好的系统中,修改一个文件,只需要重新编译数个,甚至是一个文件。

某产品曾经做过一个实验,把所有函数的实现通过工具注释掉,其编译时间只减少了不到10%,究其原因,在于A包含B,B包含C,C包含D,最终几乎每一个源文件都包含了项目组所有的头文件,从而导致绝大部分编译时间都花在解析头文件上。

某产品更有一个“优秀实践”,用于将.c文件通过工具合并成一个比较大的.c文件,从而大幅度提高编译效率。

其根本原因还是在于通过合并.c文件减少了头文件解析次数。

但是,这样的“优秀实践”是对合理划分.c文件的一种破坏。

大部分产品修改一处代码,都得需要编译整个工程,对于TDD之类的实践,要求对于模块级别的编译时间控制在秒级,即使使用分布式编译也难以实现,最终仍然需要合理的划分头文件、以及头文件之间的包含关系,从根本上降低编译时间。

密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第7页,共61页Page7,Total61googleC+StyleGuide1.2头文件依赖章节也给出了类似的阐述:

若包含了头文件aa.h,则就引入了新的依赖:

一旦aa.h被修改,任何直接和间接包含aa.h代码都会被重新编译。

如果aa.h又包含了其他头文件如bb.h,那么bb.h的任何改变都将导致所有包含了aa.h的代码被重新编译,在敏捷开发方式下,代码会被频繁构建,漫长的编译时间将极大的阻碍频繁构建。

因此,我们倾向于减少包含头文件,尤其是在头文件中包含头文件,以控制改动代码后的编译时间。

合理的头文件划分体现了系统设计的思想,但是从编程规范的角度看,仍然有一些通用的方法,用来合理规划头文件。

本章节介绍的一些方法,对于合理规划头文件会有一定的帮助。

原则原则1.11.1头文件中适合放置接口的声明,不适合放置实现。

头文件中适合放置接口的声明,不适合放置实现。

说明:

头文件是模块(Module)或单元(Unit)的对外接口。

头文件中应放置对外部的声明,如对外提供的函数声明、宏定义、类型定义等。

内部使用的函数(相当于类的私有方法)声明不应放在头文件中。

内部使用的宏、枚举、结构定义不应放入头文件中。

变量定义不应放在头文件中,应放在.c文件中。

变量的声明尽量不要放在头文件中,亦即尽量不要使用全局变量作为接口。

变量是模块或单元的内部实现细节,不应通过在头文件中声明的方式直接暴露给外部,应通过函数接口的方式进行对外暴露。

即使必须使用全局变量,也只应当在.c中定义全局变量,在.h中仅声明变量为全局的。

延伸阅读材料:

C语言接口与实现(DavidR.Hanson著傅蓉周鹏张昆琪权威译机械工业出版社2004年1月)(英文版:

CInterfacesandImplementations)原则原则1.21.2头文件应当职责单一头文件应当职责单一。

说明:

头文件过于复杂,依赖过于复杂是导致编译时间过长的主要原因。

很多现有代码中头文件过大,职责过多,再加上循环依赖的问题,可能导致为了在.c中使用一个宏,而包含十几个头文件。

示例:

如下是某平台定义WORD类型的头文件:

#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第8页,共61页Page8,Total61typedefunsignedshortWORD;这个头文件不但定义了基本数据类型WORD,还包含了stdio.hsyslib.h等等不常用的头文件。

如果工程中有10000个源文件,而其中100个源文件使用了stdio.h的printf,由于上述头文件的职责过于庞大,而WORD又是每一个文件必须包含的,从而导致stdio.h/syslib.h等可能被不必要的展开了9900次,大大增加了工程的编译时间。

原则原则1.31.3头文件应向稳定的方向包含头文件应向稳定的方向包含。

说明:

头文件的包含关系是一种依赖,一般来说,应当让不稳定的模块依赖稳定的模块,从而当不稳定的模块发生变化时,不会影响(编译)稳定的模块。

就我们的产品来说,依赖的方向应该是:

产品依赖于平台,平台依赖于标准库。

产品依赖于平台,平台依赖于标准库。

某产品线平台的代码中已经包含了产品的头文件,导致平台无法单独编译、发布和测试,是一个非常糟糕的反例。

除了不稳定的模块依赖于稳定的模块外,更好的方式是两个模块共同依赖于接口除了不稳定的模块依赖于稳定的模块外,更好的方式是两个模块共同依赖于接口,这样任何一个模块的内部实现更改都不需要重新编译另外一个模块。

在这里,我们假设接口本身是最稳定的。

延伸阅读材料:

编者推荐开发人员使用“依赖倒置依赖倒置”原则,即由使用者制定接口,服务提供者实现接口,更具体的描述可以参见敏捷软件开发:

原则、模式与实践(RobertC.Martin著邓辉译清华大学出版社2003年9月)的第二部分“敏捷设计”章节。

规则规则1.11.1每一个每一个.c.c文件应有一个同名文件应有一个同名.h.h文件,用于声明需要对外公开的接口。

文件,用于声明需要对外公开的接口。

说明:

如果一个.c文件不需要对外公布任何接口,则其就不应当存在,除非它是程序的入口,如main函数所在的文件。

现有某些产品中,习惯一个.c文件对应两个头文件,一个用于存放对外公开的接口,一个用于存放内部需要用到的定义、声明等,以控制.c文件的代码行数。

编者不提倡这种风格。

这种风格的根源在于源文件过大,应首先考虑拆分.c文件,使之不至于太大。

另外,一旦把私有定义、声明放到独立的头文件中,就无法从技术上避免别人include之,难以保证这些定义最后真的只是私有的。

本规则反过来并不一定成立。

有些特别简单的头文件,如命令ID定义头文件,不需要有对应的.c存在。

示例:

对于如下场景,如在一个.c中存在函数调用关系:

voidfoo()bar();voidbar()Dosomething;必须在foo之前声明bar,否则会导致编译错误。

这一类的函数声明,应当在.c的头部声明,并声明为static的,如下:

staticvoidbar();voidfoo()bar();密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第9页,共61页Page9,Total61voidbar()Dosomething;规则规则1.21.2禁止头文件循环依赖禁止头文件循环依赖。

说明:

头文件循环依赖,指a.h包含b.h,b.h包含c.h,c.h包含a.h之类导致任何一个头文件修改,都导致所有包含了a.h/b.h/c.h的代码全部重新编译一遍。

而如果是单向依赖,如a.h包含b.h,b.h包含c.h,而c.h不包含任何头文件,则修改a.h不会导致包含了b.h/c.h的源代码重新编译。

规则规则1.31.3.c/.h.c/.h文件禁止包含用不到的头文件文件禁止包含用不到的头文件。

说明:

很多系统中头文件包含关系复杂,开发人员为了省事起见,可能不会去一一钻研,直接包含一切想到的头文件,甚至有些产品干脆发布了一个god.h,其中包含了所有头文件,然后发布给各个项目组使用,这种只图一时省事的做法,导致整个系统的编译时间进一步恶化,并对后来人的维护造成了巨大的麻烦。

规则规则1.41.4头文件应当自包含头文件应当自包含。

说明:

简单的说,自包含就是任意一个头文件均可独立编译。

如果一个文件包含某个头文件,还要包含另外一个头文件才能工作的话,就会增加交流障碍,给这个头文件的用户增添不必要的负担。

示例:

如果a.h不是自包含的,需要包含b.h才能编译,会带来的危害:

每个使用a.h头文件的.c文件,为了让引入的a.h的内容编译通过,都要包含额外的头文件b.h。

额外的头文件b.h必须在a.h之前进行包含,这在包含顺序上产生了依赖。

注意:

该规则需要与“.c/.h文件禁止包含用不到的头文件”规则一起使用,不能为了让a.h自包含,而在a.h中包含不必要的头文件。

a.h要刚刚可以自包含,不能在a.h中多包含任何满足自包含之外的其他头文件。

规则规则1.51.5总是编写内部总是编写内部#include#include保护符(保护符(#define#define保护)保护)。

说明:

多次包含一个头文件可以通过认真的设计来避免。

如果不能做到这一点,就需要采取阻止头文件内容被包含多于一次的机制。

通常的手段是为每个文件配置一个宏,当头文件第一次被包含时就定义这个宏,并在头文件被再次包含时使用它以排除文件内容。

所有头文件都应当使用#define防止头文件被多重包含,命名格式为FILENAME_H,为了保证唯一性,更好的命名是PROJECTNAME_PATH_FILENAME_H。

注:

没有在宏最前面加上“_,即使用FILENAME_H代替_FILENAME_H_,是因为一般以_和”_开头的标识符为系统保留或者标准库使用,在有些静态检查工具中,若全局可见的标识符以_开头会给出告警。

定义包含保护符时,应该遵守如下规则:

1)保护符使用唯一名称;2)不要在受保护部分的前后放置代码或者注释。

密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第10页,共61页Page10,Total61示例:

假定VOS工程的timer模块的timer.h,其目录为VOS/include/timer/timer.h,应按如下方式保护:

#ifndefVOS_INCLUDE_TIMER_TIMER_H#defineVOS_INCLUDE_TIMER_TIMER_H.#endif也可以使用如下简单方式保护:

#ifndefTIMER_H#defineTIMER_H.#endif例外情况:

头文件的版权声明部分以及头文件的整体注释部分(如阐述此头文件的开发背景、使用注意事项等)可以放在保护符(#ifndefXX_H)前面。

规则规则1.61.6禁止在头文件中定义变量。

禁止在头文件中定义变量。

说明:

在头文件中定义变量,将会由于头文件被其他.c文件包含而导致变量重复定义。

规则规则1.71.7只能通过包含头文件的只能通过包含头文件的方式使用其他方式使用其他.c.c提供的接口,禁止在提供的接口,禁止在.c.c中通过中通过externextern的方式使用外部的方式使用外部函数接口、变量函数接口、变量。

说明:

若a.c使用了b.c定义的foo()函数,则应当在b.h中声明externintfoo(intinput);并在a.c中通过#include来使用foo。

禁止通过在a.c中直接写externintfoo(intinput);来使用foo,后面这种写法容易在foo改变时可能导致声明和定义不一致。

规则规则1.81.8禁止在禁止在externCexternC中包含头文件中包含头文件。

说明:

在externC中包含头文件,会导致externC嵌套,VisualStudio对externC嵌套层次有限制,嵌套层次太多会编译错误。

在externC中包含头文件,可能会导致被包含头文件的原有意图遭到破坏。

例如,存在a.h和b.h两个头文件:

#ifndefA_H_#defineA_H_#ifdef_cplusplusvoidfoo(int);#definea(value)foo(value)#elsevoida(int)#endif#endif/*A_H_*/#ifndefB_H_#defineB_H_#ifdef_cplusplusexternC#endif#includea.hvoidb();#ifdef_cplusplus#endif#endif/*B_H_*/使用C+预处理器展开b.h,将会得到密级:

confidentialitylevelDKBA2826-2011.52011-06-02华为机密,未经许可不得扩散HuaweiConfidential第11页,共61页Page11,Total61externCvoidfoo(int);voidb();按照a.h作者的本意,函数foo是一个C+自由函数,其链接规范为C+。

但在b.h中,由于#includea.h被放到了externC的内部,函数foo的链接规范被不正确地更改了。

示例:

错误的使用方式:

extern“C”#include“xxx.h”.正确的使用方式:

#include“xxx.h”extern“C”.建议建议1.11.1一个模块通常包含多个一个模块通常包含多个.c.c文件,建议放在同一个目录下,目录名即为模块名。

为方便外部使文件,建议放在同一个目录下,目录名即为模块名。

为方便外部使用者,建议每一个模块提供一个用者,建议每一个模块提供一个.h.h,文件名为目录名。

,文件名为目录名。

说明:

需要注意的是,这个.h并不是简单的包含所有内部的.h,它是为了模块使用者的方便,对外整体提供的模块接口。

以Googletest(简称GTest)为例,GTest作为一个整体对外提供C+单元测试框架,其1.5版本的gtest工程下有6个源文件和12个头文件。

但是它对外只提供一个gtest.h,只要包含gtest.h即可使用GTest提供的所有对外提供的功能,使用者不必关系GTest内部各个文件的关系,即使以后GTest的内部实现改变了,比如把一个源文件c拆成两个源文件,使用者也不必关心,甚至如果对外功能不变,连重新编译都不需要。

对于有些模块,其内部功能相对松散,可能并不一定需要提供这个.h,而是直接提供各个子模块或者.c的头文件。

比如产品普遍使用的VOS,作为一个大模块,其内部有很多子模块,他们之间的关系相对比较松散,就不适合提供一个vos.h。

而VOS的子模块,如Memory(仅作举例说明,与实际情况可能有所出入),其内部实现高度内聚,虽然其内部实现可能有多个.c和.h,但是对外只需要提供一个Memory.h声明接口。

建议建议1.21.2如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的.h.h,文件名为子模块名。

,文件名为子模块名。

说明:

降低接口使用者的编写难度。

说明:

降低接口使用者的编写难度。

建议建议1.31.3头文件不要使用非习惯用法的扩展名,如头文件不要使用非习惯用法的扩展名,如.inc.inc。

说明:

目前很多产品中使用了.inc作为头文件扩展名,这不符合c语言的习惯用法。

在使用.inc作为头文件扩展名的产品,习惯上用于标识此头文件为私有头文件。

但是从产品的实际代码来看,这一条并没有被遵守,一个.inc文件被多个.c包含比比皆是。

本规范不提倡将私有定义单独放在头文件中,具密级:

confidentialitylevelDKBA2826-2011.52011-06-0

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

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2