【编程语言 | C语言】C 语言编程规范
欢迎大家访问我的个人博客:吴佳轶 | WuJiaYi,第一时间获取最新的文章。
规范制定说明
本套C语言编程规范为提高代码质量、便于维护、协同编码、可移植等特点而编写。要求所有参与编码人员要严格遵循本编程规范。
参考文献:
- 华为C语言开发编程规范。
- 阿里巴巴Java开发手册。
【示例】 展示的代码片段,做参考使用。
【原则】 在编写程序时必须严格遵守的规范。
【建议】 在编写程序时需要认真参考的规范。
【粗体】 在规范中特别强调的内容。
标识符命名与定义
建议使用unix like风格给标识符命名,即单词用小写字母,每个单词直接用下划线“_”分割。
例如:text_mutex,test_one,kernel_text_address。
我们对标识符定义主要是为了让团队的代码看起来尽可能统一,有利于代码的后续阅读和修改。标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。尽可能给出描述性名称,不要节约空间,让别人很快理解你的代码更重要。
【示例】
常见缩写:
buffer 可缩写为 buffcommand 可缩写为 cmdcompare 可缩写为 cmperror 可缩写为 errinitialize 可缩写为 initmaximum 可缩写为 maxmessage 可缩写为 msgparameter 可缩写为 paraprevious 可缩写为 prevregister 可缩写为 regtemp 可缩写为 tmp
【示例】
好的命名:
int error_number;
int number_of_completed_connection;
不好的命名:
int n;
int n_comp_conns;
【原则】
- 除了常见的通用缩写以外,不得使用单词缩写,不得使用汉语拼音。
- 代码中的命名均不能以下划线开始,也不能以下划线符号结束。
- 禁止使用单字母命名变量,但允许且仅能定义i、j、k、l作为局部循环变量。
- 严禁使用未经初始化的变量作为右值。
- 全局变量应增加“g_”前缀,全局数组应增加“a_”前缀。
【建议】
- 尽量避免名字中出现数字编号,除非逻辑上的确需要编号。
- 重构/修改部分代码时,应保持和原有代码的命名风格一致。
- 常量和宏的定义应该全部大写,多个单词应使用“_”相隔。
- 变量初始化必须赋予初值。
函数
函数设计的精髓:编写整洁函数,同时把代码有效组织起来。
整洁函数要求:代码简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。
说明:扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。
设计高扇入,合理扇出(小于7)的函数。扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;而扇出过小,例如:总是1,表明函数的调用层次可能过多,这样不利于程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。通常函数比较合理的扇出(调度函数除外)通常是3~5。扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。扇出太小,可把下级函数进一步分解多个函数,或合并到上级函数中。当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。
扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。公共模块中的函数及底层函数应该有较高的扇入。
较良
【示例】
static void calibrate_run_measurement_overhead(void)
{u64 T0, T1, delta, min_delta = 1000000000ULL;int i;for (i = 0; i < 10; i++){T0 = get_nsecs();burn_nsecs(0);T1 = get_nsecs();delta = T1-T0;min_delta = min(min_delta, delta);}run_measurement_overhead = min_delta;printf("run measurement overhead: %Ld nsecs\n", min_delta);
}
【原则】
- 避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。
- 避免函数过长,新增函数不超过50行(非空非注释行)。
- 设计高扇入,合理扇出(小于7)的函数。
- 废弃代码(没有被调用的函数和变量)要及时清除。
【建议】
- 一个函数仅完成一个功能。
- 重复代码应该尽可能提炼成函数。
- 函数的参数个数不超过5个。
关于注释
建议所有变量(包括全局变量)定义语句的上方使用单行注释加以阐述和说明此变量的作用,语言简洁、易懂。最好不要超过一行。
优秀的代码可以自我解释,不通过注释即可轻易读懂。优秀的代码不写注释也可轻易读懂,注释无法把糟糕的代码变好,需要很多注释来解释的代码往往存在坏味道,需要重构。
【示例】
注释不能消除代码的坏味道:
/* 判断m是否为素数*/
/* 返回值:: 是素数,: 不是素数*/
int p(int m)
{int k = sqrt(m);for (int i = 2; i <= k; i++)if (m % i == 0)break; /* 发现整除,表示m不为素数,结束遍历*//* 遍历中没有发现整除的情况,返回*/if (i > k)return 1;/* 遍历中没有发现整除的情况,返回*/elsereturn 0;
}
重构代码后,不需要注释:
int IsPrimeNumber(int num)
{int sqrt_of_num = sqrt (num);for (int i = 2; i <= sqrt_of_num; i++){if (num % i == 0){return FALSE;}}return TRUE;
}
【示例】
功能说明:
/** lib/prio_tree.c - priority search tree** Copyright (C) 2004, Rajesh Venkatasubramanian <vrajesh@umich.edu>** This file is released under the GPL v2.** Based on the radix priority search tree proposed by Edward M. McCreight* SIAM Journal of Computing, vol. 14, no.2, pages 257-276, May 1985** 02Feb2004 Initial version*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/prio_tree.h>
单行注释:
/** Maximum heap_index that can be stored in a PST with index_bits bits*/
static inline unsigned long prio_tree_maxindex(unsigned int bits)
{return index_bits_to_maxindex[bits - 1];
}
【原则】
- 文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者姓名、工号、内容、功能说明、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。
- 如果模块或函数有重大重构或修改时应标明修改时间和修改内容。
- 注释的内容要清楚、明了,含义准确,防止注释二义性。
- 修改代码时,维护代码周边的所有注释,以保证注释与代码的一致性。不再有用的注释要删除。
- 函数声明处注释描述函数功能、性能及用法,包括输入和输出参数、函数返回值、可重入的要求等;定义处详细描述函数功能和实现要点,如实现的简要步骤、实现的理由、设计约束等。
- 全局变量要有较详细的注释,包括对其功能、取值范围以及存取时注意事项等的说明。
【建议】
- 对于每个模块应使用块注释在模块上方说明作用和功能,语言简洁、易懂。
- 建议不要在模块或函数内部加入过多的注释影响阅读。注释的作用是解释难以表达的抽象意图,而不是重复描述代码。
- 建议注释应放在其代码上方相邻位置或右方,不可放在下面。如放于上方则需与其上面的代码用空行隔开,且与下方代码缩进相同。
排版与格式
程序的可读性和可维护性除了编码好坏外,还要很重要的因素是编码时的排版与格式。应该注意排版风格一致、美观。
【示例】
int swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,enum dma_data_direction dir, struct dma_attrs *attrs)
{struct scatterlist *sg;int i;BUG_ON(dir == DMA_NONE);for_each_sg(sgl, sg, nelems, i) {phys_addr_t paddr = sg_phys(sg);dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);if (swiotlb_force || !dma_capable(hwdev, dev_addr, sg->length)) {void *map = map_single(hwdev, sg_phys(sg),sg->length, dir);if (!map) {/* Don't panic here, we expect map_sg users to do proper error handling. */swiotlb_full(hwdev, sg->length, dir, 0);swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,attrs);sgl[0].dma_length = 0;return 0;}sg->dma_address = swiotlb_virt_to_bus(hwdev, map);} else{sg->dma_address = dev_addr;}sg->dma_length = sg->length;}return nelems;
}
EXPORT_SYMBOL(swiotlb_map_sg_attrs);
【原则】
- 程序块应采用缩进风格编写,每级缩进为1个tab(1个tab设为4个空格)。
- if、for、do、while、case、switch、default等语句独占一行。
- 相对独立的程序块之间、变量说明之后必须加空行。
【建议】
- 多个短语句(包括赋值语句)不允许写在同一行内,即一行只写一条语句。
- 任何运算符左右必须加一个空格。
- 一条语句不能过长,如不能拆分需要分行写。一行到底多少字符换行比较合适,产品可以自行确定。
- 在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。
- 注释符(包括„/‟„//‟„/‟)与注释内容之间要用一个空格进行分隔。
- 所有花括号必须独占一行,if语句即使一条表达式也要加花括号。
程序效率
本章节后面所有的原则和建议,都应在不影响前述可读性等质量属性的前提下实施。不能一味地追求代码效率,而对软件的正确、简洁、可维护性、可靠性及可测性造成影响。
记住:让一个正确的程序更快速,比让一个足够快的程序正确,要容易得太多。大多数时候,不要把注意力集中在如何使代码更快上,应首先关注让代码尽可能地清晰易读和更可靠。
【示例】
int foo()
{if (异常条件){异常处理;return ERR_CODE_1;}if (异常条件){异常处理;return ERR_CODE_2;}正常处理;return SUCCESS;
}
上面的示例代码看起来很清晰,而且也避免了大量的if else嵌套。但是从性能的角度来看,应该把执行概率较大的分支放在前面处理,由于正常情况下的执行概率更大,若首先考虑性能。应如下书写:
int foo()
{if (满足条件){正常处理;return SUCCESS;}else if (概率比较大的异常条件){异常处理;return ERR_CODE_1;}else{异常处理;return ERR_CODE_2;}
}
除非证明foo函数是性能瓶颈,否则按照本规则,应优先选用前面一种写法。
【原则】
- 通过对数据结构、程序算法的优化来提高效率。
- 将不变条件的计算移到循环体外。
【编程语言 | C语言】C 语言编程规范相关推荐
- 嵌入式C语言编程规范
前言 代码首先是给人看的,其次才是给机器执行的,因此一般情况下代码的可读性优先于性能,只有确定性能是瓶颈时,才需要主动优化. 可读性高的代码应当是易于理解并且易于实现的,代码越长越难看懂,可能出错的地 ...
- 嵌入式软件工程师养成记-基本功能篇之c语言编程规范
基本功能篇之c语言编程规范 为什么还在用c语言开发 首先将编程语言按照开发效率粗略的分为三个等级,低中高,对应的语言有汇编(低).c/c++(中).python(高).越低级的语言.开发效率越低.但是 ...
- 华为c语言编程规范_单片机开发之C语言编程基本规范
为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范.本标准规定了程序设计人员进行程序设计时必须遵循的规范.本规范主要针对单片机编程语言和08编译器而言,包括排版.注释.命名.变量 ...
- C语言代码规范(编程规范)
首页 > 编程笔记 > C语言笔记 阅读:7,165 C语言代码规范(编程规范) C语言中文网推出辅导班啦,包括「C语言辅导班.C++辅导班.算法/数据结构辅导班」,全部都是一对一教学:一 ...
- 语言android编程规范,计算机语言编程规范-在路上.PDF
计算机语言编程规范-在路上.PDF 计算机语言编程规范 版本:v0.8 Crifan Li 摘要 本文主要介绍了各种计算机语言编程规范的通用知识和某个特定语言的编程规范. 本文提供多种格式供: 在线阅 ...
- C语言编程规范 clean code
目的 规则并不是完美的,通过禁止在特定情况下有用的特性,可能会对代码实现造成影响.但是我们制定规则的目的"为了大多数程序员可以得到更多的好处", 如果在团队运作中认为某个规则无法遵 ...
- 华为c语言编程规范_C语言编程规范
一.简介 代码编写规则应该在建立一个工程项目之前,应该贯穿整个项目的始终,以保证代码的一致性.采用标准的代码编写惯例,可以大大简化项目的维护负担.采用一种好的风格,以达到以下目的:可移植性.连贯.整洁 ...
- c语言编程题一空几分,C语言编程规范试题
C语言编程规范试题 [说明]: 1.本试题中不考虑头文件引用问题(假定已经包含正确的头文件),C语言的标准函数都可用: 2.如果不特别说明,假定程序运行环境为:操作系统Windows 2000, VC ...
- 迟思堂工作室编程规范:单片机C语言
迟思堂工作室编程规范:单片机C语言 1.头文件: 头文件一般是声明外部或内部变量.函数以及定义的宏.一般不作变量的初始化. 其格式为: #ifndef __MY_TYPE_H__ #define __ ...
最新文章
- as 不显示gradle视图_Python构建RESTful网络服务[Django篇:基于类视图的API]
- Spring中Controller和RequestMapping的详解
- matlab 高斯模糊_摸鱼 | 茴香豆的“茴”有四种写法,模糊有几种糊法?
- iOS之深入解析Runtime的objc_msgSend“慢速查找”底层原理
- c语言打印树形图形,数据结构C语言版树形结构.ppt
- uniapp /deep/设置uni-app组件样式时 h5生效 小程序失效问题解决
- intellij idea 好用的快捷键(mac版)
- IntelliJ IDEA 添加copyright
- Python之网络爬虫(爬虫基本认知、网络爬虫之路)
- Red5开发第一步-Hello World
- uestc 方老师的分身 II
- Python 代码使用pdb调试技巧
- vscode在vue页面中书写代码没有提示!怎么破?
- jpeglib的jpeg_finish_compress函数疑似越界
- 对应node版本_Node.js 应用故障排查手册 —— Node.js 性能平台使用指南
- 怎么接入WAPI网络防止被蹭网
- 美联储加息已成“政治正确” 美元涨势难以阻挡?
- java代码整洁之道_代码整洁之道——我们是作者
- 树莓派运用阿里云API实现语音识别
- thinkDifferent思维糖果