一、简介

代码编写规则应该在建立一个工程项目之前,应该贯穿整个项目的始终,以保证代码的一致性。采用标准的代码编写惯例,可以大大简化项目的维护负担。采用一种好的风格,以达到以下目的:可移植性、连贯、整洁、易于维护、易于理解、简洁。


二、基本原则

制定标准的基本目的是加强代码的可维护性。也就是说代码必须易于阅读、易于理解、易于测试、易于移植。保持代码的简单清晰,不要在语言中使用晦涩难懂的表达,直接表明你的思想。保持一致性,尽可能使用同样的规则,避免使用复杂语句,一个语句若有太多的决策点将会使代码难于理解,尤其是对于测试。一旦修改已存在的代码,就要随时更新相关文档。


三、排版

1. 程序块缩进

程序块要采用缩进风格编写,缩进的空格数为4个。在编码之前对相关IDE进行设置,如若没有缩进设置,需要在编写完代码后使用相关工具格式化代码。

2. 代码群落加空格

相对独立的程序块之间、变量说明之后必须加空行。

不符合规范——

void *th_func(void *arg)
{int specific = (int)(int *)arg;for (int i = 0; i <= specific; i++){printf(“%lx run %d mn”, pthread_self(), i);int time = (int)(drand48() * 10000);usleep(time);}return (void *)0;
}

符合规范——

void *th_func(void *arg)
{int specific = (int)(int *)arg;for (int i = 0; i <= specific; i++){printf(“%lx run %d mn”, pthread_self(), i);int time = (int)(drand48() * 10000);usleep(time);}return (void *)0;
}

3. 一行不要超过80列

较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
循环、判断等语句中若有较长的表达式或语句,则要进行适当的划分,长表达式要在低优先级操作符处分新行,操作符放在新行之首。
若函数或过程中的参数较长,则要进行适当的划分。
不允许把多个短语句写在一行中,即一行只写一条语句。

4. 流程控制语句必须用大括号包含起来

if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句无论多少行都要加大括号{}。

5. 操作符

在两个以上的关键字、变量、常量进行对等操作时。它们之间的操作符之前、之后或者前后都要加空格;进行非对等操作时,如果关系密切的立即操作符,后不应加空格。

逗号只在后面加空格——

int a, b, c;

比较操作符、赋值操作符、算术操作符、逻辑操作符、位域操作符等双目操作符前后都要加空格——

if (a == n)
a = b + c;
a *= 2;
a = b ^ 2;
pid = p->pid;

单目操作符前后不加空格——

*p = &q;
flag = !isEmpty;
++i;
j++;

if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显——

if (a >= b && c > d)

6. 函数排版

相似的模板、相似的代码顺序、相似的函数排版靠近。

7. 头文件包含次序

头文件include从抽象到具体,次序:C标准库→C++标准库→OS相关→第三方库→工程头文件。


四、注释

注释的原则是有助于对程序的阅读理解以及提供二次开发所需文档,注释标准参考Doxygen代码注释规范。遵循原则为,说明性文件、函数接口必须充分注释说明。全局变量需要说明功能及取值范围,需要自行处理资料函数需要加上使用警告信息。

不要使用注释来屏蔽代码。

关于函数和局部变量的注释,当代码已经可自注释,不用添加多余的注释。


五、标识符命名

标识符的命名要清晰明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。命名中若有使用特殊约定或缩写,则要有注释说明。整个工程自始自终的命名风格保持一致,不可来回变化。

1. 对于变量名,禁止取单个字符(如i、j、k……),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。

建议命名如下:

<数据类型>[模块名]<变量作用域><变量数据类型><变量类型><变量名>

/* 全局变量 */
int comm_giv_width;
char *comm_gcp_width;
const int comm_gic_max;/* 局部变量 */
int liv_width;
char *lcp_width;
const int lic_max = 10;/* 静态变量 */
static int lisv_width = 10;

2. 函数

全局函数,以模块名称为前缀,单词间首字母大写,例如void CommInit();头文件中声明必须包含extern关键字。
局部函数,以模块名称与下划线为前缀,单词间首字母大写;需在源文件中做前置声明。

3. 宏

以模块名称为前缀,单词间使用下划线隔开,单词字母为全大写。

4. 全局常量

以模块名称为前缀,单词间使用下划线隔开,单词字母为全大写,除了编译开关/头文件等特殊应用,应避免使用下划线开始和结尾的定义。


六、文件名

大模块之间以文件夹隔开,以功能命名,源文件与头文件一一对应。


七、可读性

1. 算法优先级

注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。防止阅读程序时产生误解,防止因默认优先级与设计思想不符而导致程序错误。

2. 使用有意义的标识代替不易理解的数字

避免使用不易理解的数字,用有意义的标识来替代。

3. 少用技巧性很高的语句

不要使用难懂的技巧性很高的语句,除非很有必要时。高技巧语句不等于高效率的程序,实际上程序的效率关键在于算法。

错误示例——

*stat_poi++ += 1;*++stat_poi += 1;

正确示例——

*stat_poi += 1;
stat_poi++;++stat_poi;
*stat_poi += 1;


八、编程建议

1. 变量与结构

  • 去掉没有必要的公共变量;
  • 仔细定义并明确公共变量的含义、作用、取值范围及公共变量;
  • 明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等;
  • 当向公共变量传递数据时,要十分小心,防止赋予不合理的值或越界等现象发生;
  • 防止局部变量与公共变量同名;
  • 严禁使用未经初始化的变量作为右值;
  • 构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一个公共变量;
  • 使用严格形式定义的、可移植的数据类型,尽量不要使用与具体硬件或软件环境关系密切的变量;
  • 结构的功能要单一,是针对一种事务的抽象;
  • 不要设计面面俱到、非常灵活的数据结构;
  • 不同结构间的关系不要过于复杂;
  • 结构中元素的个数应适中,若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数;
  • 仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间、并减少引起误用现象;
  • 结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地;
  • 留心具体语言及编译器处理不用数据类型的原则及有关细节;
  • 编程时,要注意数据类型的强制转换;
  • 对编译系统默认的数据类型转换也要有充分的认识;
  • 尽量减少没有必要的数据类型默认转换与强制转换;
  • 合理的设计数据并使用自定义数据类型,避免数据间进行不必要的类型转换;
  • 对自定义数据类型进行恰当命名,使它成为自描述性的,以提高代码可读性。注意命名方式在同一项目中的统一性;
  • 当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题。

2. 函数与过程

  • 对所调用函数的错误返回码要仔细、全面的处理;
  • 明确函数功能,精确(而不是近似)地实现函数设计;
  • 编写可重入函数时,应使用局部变量;
  • 编写可重入函数时,若使用全局变量,则应通过关中断、信号量等手段对其加以保护;
  • 在同一项目组应明确规定对接口函数参数的合法性检测应由函数调用者负责;
  • 防止将函数的参数作为工作变量;
  • 函数的规模尽量限制在150行以内,不包括注释和空行;
  • 一个函数仅完成一个功能;
  • 为简单功能编写函数;
  • 不要设计多用途而面面俱到的函数;
  • 函数的功能应该是可以预测的,保证输入数据相同就应产生同样的输出;
  • 尽量不要编写依赖其它函数内部实现的函数;
  • 避免设计多参数函数,不使用的参数从接口中去掉,函数参数不要超过4个;
  • 非调度函数应减少或防止控制参数,尽量只使用数据参数;
  • 检查函数非参数输入的有效性,如数据文件、公共变量等;
  • 函数名应准确描述函数的功能,使用动宾词组为执行某操作的函数命名。如果是OOP方法,可以只有动词(名次是对象本身),避免使用无意义或含义不清的动词为函数命名;
  • 函数的返回值要清楚明了,让使用者不容易忽视错误情况;
  • 除非必要,最好不要把与函数返回值类型不同的变量,以编译系统默认的转换方式或强制的转换方式作为返回值返回;
  • 在调用函数填写参数时,尽量减少没有必要的默认数据类型转换或强制数据类型转换;
  • 避免函数中不必要语句,防止程序中的垃圾代码;
  • 防止喊出或过程内出现随机内聚,不要将没有关联或关联很弱的语句放到同一个函数或过程中;
  • 如果多段代码执行同一功能,那么考虑将此段代码构造成一个新的函数;
  • 功能不明确、较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上级函数中,而不必单独存在;
  • 设计高扇入、合理扇出(<7)的函数;
  • 减少函数本身或函数间的递归调用;
  • 仔细分析模块的功能及性能需求,并进一步细分,同时若有必要画出有关数据流图,据此来进行模块的函数划分与组织;
  • 改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性。优化函数结构时,要遵守以下原则——

1. 不能影响函数功能的实现;
2. 仔细考查模块或函数出错处理及模块的性能要求并进行完善;
3. 通过分解或合并函数来改进软件结构;
4. 考查函数的规模,过大的要进行分解;
5. 降低函数间接口的复杂度;
6. 不同层次的函数调用要有较合理的扇入、扇出;
7. 函数功能应可预测;
8. 提高函数内聚。

  • 在多任务操作系统的环境下编译,要注意函数可重入性的构造;
  • 避免使用BOOL参数;
  • 对于提供了返回值的函数,在引用时最好使用其返回值;
  • 当一个过程(函数)汇总对较长变量(一般是结构体的成员)有较多引用时,可以用一个意义相当的宏代替。

3. 可测性

  • 在同一个项目组或产品组内,要有一套统一的,为集成测试与系统联调准备的调测开关及相关打印函数,并且要有详细的说明;
  • 在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式,信息串至少要有所在模块名及行号;
  • 编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明。测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关);
  • 在进行集成测试/系统联调之前,要构造好测试环境、测试项目以及测试用例,同时仔细分析并优化测试用例,以提高测试效率;
  • 使用断言来发现软件问题,提高代码可测性;
  • 用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况;
  • 不能用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况;
  • 对较为复杂的断言加上明确的注释;
  • 用断言确认函数的参数;
  • 用断言保证没有定义的特性或功能不被使用;
  • 用断言对程序开发环境的假设进行检查;
  • 正式软件产品中应把断言及其它调测代码去掉;
  • 在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响;
  • 用调测开关来切换软件的Debug版和Release版,而不要同时存在Debug版本和Release版本的不同源文件,减少维护的难度;
  • 在编写代码之前,应预先设计好程序调测与测试的方法和手段,并设计好各种调测开关和相应测试代码;
  • 调测开关应分为不同级别和类型;
  • 编写放错程序,然后在处理错误之后可用断言宣布发生错误。

4. 程序效率

  • 在保证软件系统的正确性、稳定性、可读性以及可测性的前提下,提高代码效率;
  • 局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响;
  • 通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率;
  • 循环体内工作量最小化;
  • 仔细分析有关算法,并进行优化;
  • 仔细考查、分析系统及模块处理输出(如事务、消息等)的方式,并加以改进;
  • 对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率;
  • 编程时,要随时留心代码效率;优化代码时,要考虑周全;
  • 不应花过多的时间拼命地提高调用不很频繁的函数代码效率;
  • 要仔细地构造或直接用汇编编写调用频繁或性能要求极高的函数;
  • 在保证程序质量的前提下,通过压缩代码量、去掉不必要代码以及减少不必要的局部和全局变量,来提高空间效率;
  • 在多重循环中,应将最忙的循环放在最内层;
  • 尽量减少循环嵌套层次;
  • 避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中;
  • 尽量用乘法或其它方法代替除法,特别是浮点运算中的除法;
  • 不要一味追求紧凑的代码。

5. 质量保证

  • 软件设计过程中构筑软件质量;
  • 代码质量保证优先原则;

1. 正确性,指程序要实现设计要求的功能;
2. 稳定性、安全性,指程序稳定、安全、可靠;
3. 可测试性,指程序要具有良好的可测试性;
4. 规范/可读性,指程序书写风格、命名规则等要符合规范;
5. 全局效率,指软件系统的整体效率;
6. 局部效率,指某个模块/子模块/函数的本身效率;
7. 个人表达方式/个人方便性,指个人编程习惯。

  • 只引用属于自己的存贮空间;
  • 防止引用已经释放的内存空间;
  • 过程/函数中分配的内存,在过程/函数退出之前要释放;
  • 过程/函数中申请的文件句柄,在过程/函数退出之前要关闭;
  • 防止内存操作越界;
  • 认真处理程序所能遇到的各种出错情况;
  • 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用;
  • 系统运行之初,要对加载到系统中的数据进行一致性检查;
  • 严谨随意更改其它模块或系统的有关设置和配置;
  • 不能随意改变与其它模块的接口;
  • 充分了解系统的接口之后,在使用系统提供的功能;
  • 编程时,防止差1错误;
  • 要时刻注意混淆的操作符,当写完程序之后,应仔细检测这些操作符;
  • 有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支;
  • Unix下,多线程中的子线程退出必须采用主动退出方式;
  • 不要滥用goto语句;
  • 不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性;
  • 除非为了满足特殊需求,避免使用嵌入式汇编;
  • 精心地构造、划分子模块,并按“接口”部分及“内核”部分合理地组织子模块,以提高“内核”部分的可移植性和可重用性;
  • 精心构造算法,并对其性能、效率进行测试;
  • 对较关键的算法最好使用其它算法来确认;
  • 时刻注意表达式是否会上溢、下溢;
  • 使用变量时要注意其边界值的情况;
  • 留心程序机器码大小(如指令空间大小、数据空间大小、堆栈空间大小等)是否超出系统有关限制;
  • 为用户提供良好的接口界面,是用户能较充分地了解系统内部运行状态及有关系统出错情况;
  • 系统应具有一定的容错能力,对一些错误时间(如用户误操作等)能进行自动补救;
  • 对一些具有危险性的操作代码(如写硬盘、删数据等)要仔细考虑,防止对数据、硬件等的安全构成危害,以提高系统的安全性;
  • 使用第三方提供的软件集开发工具包或控件时,要注意以下几点:

1. 充分了解应用接口、使用环境及使用时注意事项;
2. 不能过分相信其正确性;
3. 除非必要,不要使用不熟悉的第三方工具包与空间。

  • 资源文件需要支持多语言版本,如果资源是对语言敏感的,应让该资源与源代码文件脱离。

6. 代码编辑、编译、审查

  • 开编译器的所有警告开发对程序进行编译;
  • 在产品软件中,要统一编译开关选项;
  • 通过代码走读及审查方式对代码进行检查;
  • 测试部测试产品之前,应对代码进行抽查及评审;
  • 编写代码时,完成功能模板及自测后及时提交版本库;
  • 同项目组内,最好使用相同的编译器,并使用相同的设置选项;
  • 要小心地使用编译器提供的块拷贝功能编程;
  • 合理地设计软件系统目录,方便开发人员使用;
  • 某些语句经编译后产生警告,但如果你确认它是正确的,那么应通过某种手动去掉警告信息;
  • 使用代码检查工具对源程序检查;
  • 使用软件工具进行代码审查。

7. 代码测试、维护

  • 元测试要求至少达到语句覆盖;
  • 单元测试开始要跟踪每一条语句,并观察数据流及变量的变化;
  • 清理、整理或优化后的代码要经过审查及测试;
  • 代码版本升级要经过严格测试;
  • 使用工具软件对代码版本进行维护;
  • 正式版本上软件的任何修改都应有详细的文档记录;
  • 发现错误立即修改,并且要记录下来;
  • 关键的代码在汇编级跟踪;
  • 仔细设计并分析测试用例,是测试用例覆盖尽可能多的情况,以提高测试用例的效率;
  • 尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试;
  • 仔细测试代码处理数据、变量的边界情况;
  • 保留测试信息,以便分析、总结经验及进行更充分的测试;
  • 不应通过“试”来解决问题,应寻找问题的根本原因;
  • 对自动消失的错误进行分析,搞清楚错误是如何消失的;
  • 修改错误不仅要治标,更要治本;
  • 测试时应设法使很少发生的事件经常发生;
  • 坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题;
  • 去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的“内部寄存器”等),让函数运行的结果可预测,并使出现的错误可再现。

8. 宏

  • 用宏定义表达式时,要使用完备的括号;
  • 将宏定义的多条表达式放在大括号中;
  • 使用宏时,不允许参数发生变化;

C语言编程规范https://www.zhihu.com/video/1147146562961661952

视频下载地址:https://pan.baidu.com/s/1iEifZDpV_A8R6xQAsi7fNw

相关文档:华为技术有限公司C语言编程规范

华为c语言编程规范_C语言编程规范相关推荐

  1. c语言c99标准_C语言的三套标准:C89、C99和C11

    我们今天使用的 Windows.Linux.Mac OS 等操作系统都是由一种叫做 Unix 的系统演化而来.Unix 作为80年代主流的操作系统,是整个软件工业的基础,是现代操作系统的开山鼻祖,C语 ...

  2. c语言在线编译器_C语言和汇编语言是什么?他们之间可以有怎样的合作?为你解析...

    什么是c语言: C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言;尽管C语言提供了许 ...

  3. java和c语言的区别_C语言为何不会过时?你需要掌握多少种语言?

    关注.星标公众号,不错过精彩内容 整理/排版:付斌 转自:嵌入式ARM 01 为什么C语言不会过时 评价任何一门编程语言,都是招人骂的.永远是这样.就像是春寒料峭的季节, 街上穿棉袄和穿单衣的擦肩而过 ...

  4. c语言求素数_C语言 | 求100~200的素数

    "要成为绝世高手,并非一朝一夕,除非是天生武学奇才,但是这种人-万中无一" --包租婆这道理放在C语言学习上也一并受用.在编程方面有着天赋异禀的人毕竟是少数,我们大多数人想要从C语 ...

  5. window直接运行不需要环境的软件是什么语言开发的_C语言为何不会过时?你需要掌握多少种语言?_C 语言...

    01为什么C语言不会过时 评价任何一门编程语言,都是招人骂的.永远是这样.就像是春寒料峭的季节, 街上穿棉袄和穿单衣的擦肩而过,双方一定是同时在心里出现了两个字:"s b!"这个在 ...

  6. c语言学生综合测评系统_c语言图书管理系统_c语言学生综合测评系统_c语言个人账本管理系统...

    c语言销售管理系统设计 c语言设计管理系统,c图书管理系统设计,学生管理系统c语言,职工管理系统c语言,c语言图书管理系统,c语言成绩管理系统,c语言管理系统,c语言银行管理系统,c语言工资管理系统, ...

  7. c语言实现通讯录_C语言实现双人猜数字游戏

    点击上方"学士科技",选择"设为星标" 资讯.技术干货第一时间送达! C语言合集(基础.进阶.高级)通通有,点我点我      C语言实例 01.C语言编写简单 ...

  8. java c语言与人工智能_C语言与LISP语言的区别

    C语言:C是过程式编程语言.它被设计成使用编译器编译.该语言有少量固定数量的关键字,如if/else,for,while,..等等.我们可以使用一个以上的作业,可以用这种语言在一个语句中使用.函数也在 ...

  9. c语言图形化编程入门_C语言C++新手入门,VS2013编程器安装教程

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

最新文章

  1. 数据集获取加速神器来了!
  2. JavaScript常规语法小总节
  3. 浅谈Java解决鸡兔同笼问题的思路
  4. php模型分页代码,ThinkPHP6.0模型关联分页
  5. eclipse编译hadoop插件
  6. 【C++深度剖析教程36】深入理解函数模板
  7. ORACLE快速遍历树及join基表很大的性能问题
  8. android 各国语言对应的缩写
  9. linux下各种player不显示mkv字幕的解决
  10. c++ ——二分查找函数
  11. 微服务2——服务的注册,调用(Nacos服务注册中心+服务调用+调用负载均衡)sca-comsumersca-provider
  12. 多系统折腾记录(老电脑MBR分区)
  13. 【css】fa图标变细
  14. 超级账本学习之三:创建超级账本网络
  15. 异地恋的自愈系小故事:企鹅先生和北极熊小姐
  16. Flask_从入门到放弃?不!!!从入门到入土!!
  17. OSChina 周六乱弹 —— 女友是啥子哟?生命的最大负载?
  18. 打包文件zip压缩包返回
  19. 手写在线计算机,在线生成手写签名
  20. soapui 证书_配置https双向认证,以及用soapui调试

热门文章

  1. django项目时间与Ubuntu时间不一致
  2. 【批处理】windows环境将文件隐藏到图片中
  3. WARNING: You are using pip version 19.2.3, however version 20.1.1 is available. You should consi解决办法
  4. LinkedList源码学习
  5. 20172324 2017-2018-2《程序设计与数据结构》实验三报告
  6. oracle 时间加减
  7. 【工具与解决方案】从做项目中积累学习
  8. java获取异常堆栈详情
  9. 在Windows中为文件添加“可执行”权限(chmod +x 文件名 不起作用)
  10. 修改Linux主机名