1024G嵌入式资源免费领取:C/C++、单片机、Linux教程大合集
1024G嵌入式资源发售!包括但不限于C/C++、单片机、Linux等,关注微信公众号【嵌入式大杂烩】回复1024即可免费获取!

一、前言
刚开始学习STM32的时候,在一些比较规范的代码中看到一些变量名为ucValue、g_ucPara等形式。当时我就觉得不习惯。为什么要添加uc、g_uc等?感觉太丑了。后来才知道,这些前缀都是有约定俗成的含义,可以很容易的知道变量的数据类型。
例如:uc代表unsigned char,因此将变量命名为ucValue可以清楚地表明它是一个unsigned char变量。同样,g代表global,即全局,g_ucPara表示是unsigned char类型的全局变量。
现在我们看一下网上一些比较权威的编码标准,比如安富利的编码标准:
2. 编程规范 1. 文件和目录
(1) 文件命名
文件命名应准确、清晰地表达其内容,文件名应简洁,防止文件名过长造成不便。文件名中可以适当使用缩写。下面提供两种命名方式供参考:
(2)头文件中段落排列的顺序
// 1、文件头注释
// 2、防止重复引用头文件的设置
// 3、#include 部分
// 4、enum 常量声明
// 5、类型声明和定义,包括 struct、union、typedef 等
// 6、全局变量声明
// 7、文件级变量声明
// 8、全局或文件级函数声明
// 9、函数实现。按函数声明的顺序排列
// 10、文件尾注释
(3)引用头文件时不要使用绝对路径
如果使用绝对路径,当需要移动目录时,必须修改所有相关代码,既麻烦又不安全;如果使用相对路径,当需要移动目录时,只需要修改编译器的某个选项即可。例如:
#include “/project/inc/hello.h” /* 不应使用绝对路径 */
#include “../inc/hello.h” /* 可以使用相对路径 */
(4)引用头文件时,使用“”
#include /* 标准头文件 */
#include /* 工程指定目录头文件 */
#include “global.h” /* 当前目录头文件 */
#include “inc/config.h” /* 路径相对于当前目录的头文件 */
(5)防止头文件被重复引用
#ifndef __DISP_H /* 文件名前名加两个下划线“__”,后面加 “_H”
#define __DISP_H
...
...
#endif
(6) 头文件中只存储“声明”,不存储“定义”
(7)文件的长度
文件长度没有严格要求,但应尽量避免文件过长。一般来说,文件长度应保持在1000行以内。
2.排版
(1) 程序块应采用缩进式书写,缩进空格数为4。
(2) 相对独立的程序块之间和变量描述之后必须添加空行。
(3)长语句或函数过程参数(>80个字符)应多行书写。长表达式应在低优先级运算符处分成新行。运算符应放在新行的开头,新行应分为几行,并适当缩进,使布局整齐,语句可读。
(4)一行中不允许写多个短语句,即一行中只能写一条语句。
(5) 程序块的分隔符(如大括号“{”和“}”)应各占一行并位于同一列。
(6)对两个以上关键字、变量、常量进行等价运算时,它们之间的运算符前后、前后必须加空格;执行非等价操作时,如果是密切相关的直接运算符(如->),则其后不应加空格。
例子:
3. 评论
(1)一般情况下,源程序中有效注释的数量必须在20%以上。
注:注释的原则是帮助程序的阅读和理解。将它们添加到应该添加的地方。评论不宜过多或过少。评论语言必须准确、易懂、简洁。
(2)文件开头应说明文件版权、内容介绍、修改历史等事项。
当您创建代码以及每次更新代码时,您必须使用版本号、日期、作者、更改描述等项目标记文件的历史记录。下面是一个例子,当然不限于这种格式,但建议包含以上信息。
(3)对于函数,在函数实现之前,应给出与函数实现相关的充分、简洁的注释信息。
例子:
下面的函数注释是比较标准的。当然,不限于此格式,但建议包含上述信息。
(4)边写代码边注释,修改代码的同时修改相应的注释,保证注释和代码的一致性。不再有用的评论将被删除。
(五)注释内容必须清晰、简洁,含义准确,防止注释产生歧义。
说明:错误的评论不仅没有帮助,而且有害。注释主要解释代码做了什么(What),或者如果需要的话,解释一下
为什么这样做(Why),注释并不是用来解释它是如何实现算法的(How)。
(6) 注释中避免使用缩写,尤其是不常见的缩写。
说明:在使用缩略语之前或使用缩略语时应对缩略语进行必要的解释。
(7) 注释应该靠近它们所描述的代码,并且对代码的注释应该放在它们的上方或右侧相邻的位置(对单个语句的注释)。
不能放在下面。如果放在上面,必须用空行与上面的代码隔开。
示例:以下示例不符合规范。
例1:不规则写法
例2:不规则写法
示例3:标准写作
例4:不规范的写法,导致代码过于紧凑。
例5:标准写作
(8) 注释的缩进应与所描述的内容相同。
说明:可以使程序布局整齐,方便注释的阅读和理解。
示例1:以下示例打字不整齐,阅读起来稍有不便。
示例 2:正确的布局。
(9)变量的定义和分支语句(条件分支、循环语句等)必须写注释。
说明:这些语句往往是程序实现特定功能的关键。对于维护人员来说,好的注释有助于更好地理解程序,有时甚至比阅读设计文档更好。
(10)对于switch语句下的case语句,如果因特殊情况需要处理完一个case再进行下一个case,则必须在该case语句处理完之后、下一个case语句之前添加明确的注释。
注意:这使得程序员的意图更加清晰,有效防止break语句的无理省略。
示例(注意粗体斜体):
(11)注释格式应尽可能统一。建议使用“/.../”,因为并非所有 C 编译器都支持 C++ 注释“//”。
(12)注释应考虑程序可读性和外观布局等因素。如果使用的语言是中文和英文,建议多用中文,除非你能用英文表达得非常流利准确。
注意:注释语言不统一,影响程序的可读性和美观。为了维护人员的方便,建议使用中文。
(十三)标识符的命名应清晰、简洁、含义明确。同时使用大家基本都能理解的完整单词或缩写,避免
以免产生误会。
注:较短的单词可以通过去掉“元音”来缩写;较长的单词可以通过删除单词的前几个字母来缩写;有些单词有公认的缩写。
例:下列单词的缩写基本上大家都能认识。
temp 可缩写为 tmp;
flag 可缩写为 flg;
statistic 可缩写为 stat;
increment 可缩写为 inc;
message 可缩写为 msg;
(14) 命名中使用特殊约定或缩写的,必须注明。
注意:应在源文件的开头对文件中使用的缩写或约定进行必要的注释,特别是特殊缩写。
(15)自己独特的命名风格必须自始至终保持一致,不能来回改变。
注意:个人命名风格必须符合项目组或产品组的命名规则才可以使用。 (即只有命名规则中没有规定的地方才可以有个人的命名风格)
(16)对于变量命名,禁止使用单个字符(如i、j、k...)
建议除了具有特定含义外,还可以表明其变量类型、数据类型等,但允许使用i、j、k作为局部循环变量。如果变量尤其是局部变量用单个字符表示,很容易出错(例如i写成j),而且编译时无法检查。仅仅为了这个小错误就可能花费大量的故障排除时间。
(17) 命名规范必须与所使用的系统风格一致,并在同一项目内统一
例如,使用 UNIX 全小写和下划线样式或混合大小写方法。不要使用混合大小写和下划线的方法。使用它作为特殊标识符如m_和g_来标识成员变量或全局变量,后面可以混合大小写。
示例:不允许Add_User,允许add_user、AddUser、m_AddUser。
(18) 除非必要,不要使用数字或奇怪的字符来定义标识符。
示例:以下命名令人困惑。
应该用有意义的单词来命名:
4. 可读性
(1)注意运算符的优先级,使用括号明确表达式的运算顺序,避免使用默认优先级。
(2)避免使用难以理解的数字,用有意义的符号代替。
示例:以下程序可读性很差
应改为以下形式:
(3) 除非绝对必要,否则不要使用难以理解和技术性很强的语句。
注:高科技的说法并不等于高效率的方案。事实上,程序效率的关键在于算法。
例:下面的表达式如果不仔细考虑可能会出现问题,而且也很难理解。
应更改为以下内容:
5.变量、结构体、常量、宏
(1)为了方便书写和记忆,对变量类型重新定义如下:
(2)常见前缀类型
(3) 变量作用域前缀
为了清晰标识变量的作用域,减少命名冲突,应在变量类型前缀前添加表示变量作用域的前缀,并用下划线-分隔变量类型前缀和变量作用域前缀。
具体规则如下:
uint32_t g_ulParaWord;
uint8_t g_ucByte;
static uint32_t s_ulParaWord;
static uint8_t s_ucByte;
(4)结构体命名规则
指示类型的名称。所有名称均以小写字母标记开头,然后每个英文单词的首字母大写(包括第一个单词的首字母),其他字母小写,并以_T标识结尾。不要使用下划线分隔单词,结构变量以 t 开头。喜欢:
/* 结构体命名类型名 */
typedef struct tagBillQuery_T
{
...
}BillQuery_T;
/* 结构体变量定义 */
BillQuery_T tBillQuery;
(5) 枚举定义全部使用大写字母,以_E标记结尾。
(6) 常量、宏、模板的名称应全部大写。如果名称由多个单词组成,则单词之间用下划线分隔。
#define LOG_BUF_SIZE 8000
6. 功能
(1)函数的命名规则。
每个函数名称的前缀必须包含模块名称。模块名称采用小写形式,以区别于函数名称。
如:uartReceive(串口接收)
注意:对于非常简单的程序,可以省略模块名称。
(2) 函数的形式参数。
函数的形参均以下划线_开头,以区别于普通变量。对于没有形式参数且为空 (void) 的函数,括号紧跟在函数后面。
uint32_t uartConvUartBaud(uint32_t _ulBaud)
{
}
(3)一个函数只完成一个功能。
(4)函数名称应准确描述函数的功能,并使用动宾短语来命名执行某种操作的函数。
注意:避免使用进程、句柄等不明确的动词来命名函数,因为这些动词并没有指定要做什么。
示例:将函数命名如下。
(5) 避免设计超过五个参数的函数,并从接口中删除未使用的参数。
说明:目的是降低函数之间接口的复杂度。复杂的参数可以使用结构体来传递。
(6)调用函数填参数时,应尽量减少不必要的默认数据类型转换或强制数据类型转换。
注意:因为数据类型转换或多或少都有危险。
(7) 防止不相关的语句放入函数中。
示例:以下函数是一种随机内聚函数。
矩形的长和宽与点的坐标基本没有关系,所以上面的函数是随机内聚。应该分为以下两个功能: