实用的C语言编程规范
简介
在项目团队协作开发的情况下,编程时应该强调的一个重要方面是程序的易读性,在保证软件速度等性能指标能满足用户需求的情况下,能让其他程序员容易读懂你所编写的程序。若项目小组的所有开发人员都遵循统一的、鲜明的一套编程风格,可以让协作者、后继者和自己一目了然,在很短的时间内看清楚程序结构,理解设计的思路,大大提高代码的可读性、可重用性、程序健壮性、可移植性、可维护性,对彼此交流和协同开发将起到事半功倍的作用。
制定本编程规范的目的是为了提高软件开发效率及所开发软件的可维护性,提高软件的质量。本规范由程序风格、命名规范、注释规范、可移植性以及软件的模块化规范等部分组成。
用简单的方法去做复杂的事!!!
1 代码编写总体原则
1.1 清晰第一
清晰性是易于维护、易于重构的程序必须具备的特征。代码首先是给人读的,好的代码应该像好的文章一样发声朗读出来。
目前软件维护期成本占整个软件生命周期成本的40%-90%。根据业界经验,维护期变更代码的成本,小型系统是开发期的5倍,大型系统(100万行代码以上)可以达到100倍。业界的调查指出,开发组平均大约一半的人力用于弥补过去的错误,而不是添加新的功能来帮助公司提高竞争力。一般情况下,代码的可阅读性高于性能,只有确定性能是瓶颈时,才应该主动优化。
“程序必须为阅读它的人而编写,只是顺便用于机器执行。”
―― Harold Abelson 和 Gerald Jay
编写程序应该以人为本,计算机第二。
――Steve  McConnell
1.2 简洁为美
简洁就是易于理解并且易于实现。代码越长越难于看懂,也越容易在修改时引入错误,写的代码越多,意味着出错的地方越多,也就意味着代码的可靠性越低。因此,我们提倡大家通过编写简洁明了的代码来提升代码可靠性。废弃的代码(没有被调用的函数和全局变量)要及时清除,重复代码应该尽可能提炼成函数。
1.3 选择合适的风格,与代码原有风格保持一致
产品所有人共同分享同一种风格所带来的好处,远远超出为了统一而付出的代价。在公司已有编码规范的指导下,审慎地编排代码以使代码尽可能清晰,是一项非常重要的技能。
2 文件结构
每个C程序通常分为两个文件。一个文件用于保存程序的声明(declaration),称为头文件。另一个文件用于保存程序的实现(implementation),称为定义(definition)文件。C程序的头文件以“.h”为后缀,C程序的定义文件以“.c”为后缀。
2.1 文件信息说明
文件信息声明位于头文件和定义文件的开头(参见示例1),主要内容有:
(1) 公司名称;
(2) 文件名称;
(3) 版权信息;
(4) 当前版本,作者/修改者,完成日期;
(5) 主要函数描述;
(6) 注意事项;
示例1
2.2 头文件的结构
头文件由三部分内容组成:
(1) 头文件开头处的文件信息说明(参见示例1)
(2) 预处理块;
(3) 函数和类结构声明等。
原则2.2.1 为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块;单词间以下划线“_”连接,例如有头文件名称为“filesystem.h”,则定义如下:“#ifndef    _FILE_SYSTEM_H_”。
原则2.2.2 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)
原则2.2.3 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)
原则2.2.4 头文件中只存放“声明”而不存放“定义”。
原则2.2.5 头文件中应包含所有定义文件所定义的函数声明,如果一个头文件对应多个定义文件,则不同定义文件内实现的函数要分开声明,并作注释以解释所声明的函数从属于那一个定义文件。
原则2.2.6 .c/.件禁止包含用不到的头文件。很多系统中头文件包含关系复杂,开发人员为了省事起见,可能不会去一一钻研,直接包含一切想到的头文件,甚至有些产品干脆发布了一个god.h,其中包含了所有头文件,然后发布给各个项目组使用,这种只图一时省事的做法,导致整个系统的编译时间进一步恶化,并对后来人的维护造成了巨大的麻烦。
2.3 函数编写规则
函数设计的精髓:编写整洁函数,同时把代码有效组织起来。
整洁函数要求:代码简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。
原则2.3.1  一个函数仅完成一件功能。
说明:一个函数实现多个功能给开发、使用、维护都带来很大的困难。将没有关联或者关联很弱的语句放到同一函数中,会导致函数职责不明确,代码混乱,难以理解,难以测试和改动。
延伸阅读材料:《敏捷软件开发:原则、模式与实践》 第八章,单一职责原则(SRP)。
原则2.3.2 重复代码应该尽可能提炼成函数。
说明:重复代码提炼成函数可以带来维护成本的降低。
项目组应当使用代码重复度检查工具,在持续集成环境中持续检查代码重复度指标变化趋势,并对新增重复代码及时重构。当一段代码重复两次时,即应考虑消除重复,当代码重复超过三次时,应当立刻着手消除重复。
原则2.3.3 避免函数过长,新增函数不超过50行(非空非注释行)。
说明:本规则仅对新增函数做要求,对已有函数修改时,建议不增加代码行。 过长的函数往往意味着函数功能不单一,过于复杂
函数的有效代码行数,即非空非注释行应当在[1,50]区间。
原则2.3.4 避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。
说明:本规则仅对新增函数做要求,对已有的代码建议不增加嵌套层次。函数的代码块嵌套深度指的是函数中的代码控制块(例如:if、for、while、switch等)之间互相包含的深
度。每级嵌套都会增加阅读代码时的脑力消耗,因为需要在脑子里维护一个“栈”(比如,进入条件语句、进入循环„„)。应该做进一步的功能分解,从而避免使代码的阅读者一次记住太多的上下文。
原则2.3.5  废弃代码(没有被调用的函数和变量)要及时清除。
说明:程序中的废弃代码不仅占用额外的空间,而且还常常影响程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。
原则2.3.6  函数不变参数使用const。
说明:不变的值更易于理解/跟踪和分析,把const作为默认选项,在编译时会对其进行检查,使代码更牢固/更安全。
原则2.3.7 函数的参数个数不超过5个。
说明:函数的参数过多,会使得该函数易于受外部(其他部分的代码)变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。 函数的参数个数不要超过5个,如果超过了建议拆分为不同函数。
原则2.3.8 在源文件范围内声明和定义的所有函数,除非外部可见否则应该增加static关键字。
最容易上手的编程语言说明:如果一个函数只是在同一文件中的其他地方调用,那么就用static声明。使用static确保只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性。
3 标示符的命名规则
目前比较使用的如下几种命名风格:
unix like风格:单词用小写字母,每个单词直接用下划线„_‟分割,例如text_mutex,kernel_text_address。
Windows风格:大小写字母混用,单词连在一起,每个单词首字母大写。不过Windows风格如果遇到大写专有用语时会有些别扭,例如命名一个读取RFC文本的函数,命令为ReadRFCText,看起来就没有unix  like的read_rfc_text清晰了。
匈牙利命名法:是计算机程序设计中的一种命名规则,用这种方法命名的变量显示了其数据类型。匈牙利命名主要包括三个部分:基本类型、一个或更多的前缀、一个限定词。实际上,各种风格都有其优势也有其劣势,而且往往和个人的审美观有关。我们对标识符定义主要是为了让团队的代码看起来尽可能统一,有利于代码的后续阅读和修改。
原则3.1 标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
说明:尽可能给出描述性名称,不要节约空间,让别人很快理解你的代码更重要。
示例:好的命名:即使不注释也能理解。
不好的命名:使用模糊的缩写或随意的字符。
原则3.2 除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音。
说明:较短的单词可通过去掉“元音”形成缩写,较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,常用单词的缩写必须统一。协议中的单词的缩写与协议保持一致。对于某个系统使用的专用缩写应该在注视或者某处做统一说明。
示例:一些常见可以缩写的例子:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。