1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 【编程语言 | C语言】C 语言编程规范

【编程语言 | C语言】C 语言编程规范

时间:2020-05-16 15:06:20

相关推荐

【编程语言 | C语言】C 语言编程规范

欢迎大家访问我的个人博客:吴佳轶 | WuJiaYi,第一时间获取最新的文章。

规范制定说明

本套C语言编程规范为提高代码质量、便于维护、协同编码、可移植等特点而编写。要求所有参与编码人员要严格遵循本编程规范。

参考文献:

华为C语言开发编程规范。阿里巴巴Java开发手册。

示例】 展示的代码片段,做参考使用。

原则】 在编写程序时必须严格遵守的规范。

建议】 在编写程序时需要认真参考的规范。

粗体】 在规范中特别强调的内容。

标识符命名与定义

建议使用unix like风格给标识符命名,即单词用小写字母,每个单词直接用下划线“_”分割。

例如:text_mutextest_onekernel_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;

原则

除了常见的通用缩写以外,不得使用单词缩写,不得使用汉语拼音。代码中的命名均不能以下划线开始,也不能以下划线符号结束。禁止使用单字母命名变量,但允许且仅能定义ijkl作为局部循环变量。 严禁使用未经初始化的变量作为右值。全局变量应增加“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) , 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** 02Feb 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函数是性能瓶颈,否则按照本规则,应优先选用前面一种写法。

原则

通过对数据结构、程序算法的优化来提高效率。将不变条件的计算移到循环体外。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。