目录
前言
本编程规范是个人工作十几年来,近些年形成较为稳定的版本,已被工作的公司采纳为公司编程规范!本规范主要借鉴了一些大公司(华为,百度,腾讯,阿里巴巴,谷歌,苹果,微软,ARM,ST.....)的编程规范和风格,吸收它们的共性和个别优秀的地方。在一些细节方面请教了一些几十年的老工程师和一些华为等大公司软件工程师!
本人曾创造过自己的编程风格,也曾想创造出世界上最完美的编程规范和风格,在当时的技术水平和行业局限下,自我感觉还是挺好的!随着经验的丰富,接触的技术越来越多,发现当初的一些规则和适用的环境已不再适用,甚至有些鸡肋,还增加了负担!在这方面也耗费很多没有价值的时间!后来痛定思痛改变编程规范和风格。不再原创,要与世界接轨,用符合当下所处大行业较为流行的,大公司通用的、大公司个别优秀的风格规范作为自己的编程规范和风格,简单说就是吸收大家之长处和共性,这样换了工作也能适用,新人进入也能快速适应,因为这些大多数人的规范和风格,少数服从多数。
不要试图去创造最完美的编程规范和风格,每种风格都有长处和短处,这些不是我们的工作重心!编程规范和风格是为了给人看的,方便人们交流和阅读,每个人的喜欢都不同,很难满足和统一,如同世界很难统一一样。做到求同存异,兼容并包就可以了!编程规范和风格好与坏对芯片来说都一样,最终都要被翻译成机器码的!
第1章 文件
每个 C++/C 程序通常分为两个文件。一个文件用于保存程序的声明(declaration),称为头文件。另一个文件用于保存程序的实现(implementation),称为定义(definition)文件。
C++/C 程序的头文件以“.h”为后缀,C 程序的定义文件以“.c”为后缀,C++程序的定义文件通常以“.cpp”为后缀(也有一些系统以“.cc”或“.cxx”为后缀)。
1.1 头文件
对于C语言来说,头文件的设计体现了大部分的系统设计。不合理的头文件布局是编译时间过长的根因。头文件主要由三部分内容组成:头文件注释;预处理块;函数声明等。
通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
某产品曾经做过一个实验,把所有函数的实现通过工具注释掉,其编译时间只减少了不到10%,究其原因,在于A包含B,B包含C,C包含D,最终几乎每一个源文件都包含了项目组所有的头文件,从而导致绝大部分编译时间都花在解析头文件上。
某产品更有一个“优秀实践”,用于将.c文件通过工具合并成一个比较大的.c文件,从而大幅度提高编译效率。其根本原因还是在于通过合并.c文件减少了头文件解析次数。但是,这样的“优秀实践”是对合理划分.c文件的一种破坏。
大部分产品修改一处代码,都得需要编译整个工程,对于TDD之类的实践,要求对于模块级别的编译时间控制在秒级,即使使用分布式编译也难以实现,最终仍然需要合理的划分头文件、以及头文件之间的包含关系,从根本上降低编译时间。
《google C++ Style Guide》1.2 头文件依赖 章节也给出了类似的阐述:若包含了头文件aa.h,则就引入了新的依赖:一旦aa.h被修改,任何直接和间接包含aa.h代码都会被重新编译。如果aa.h又包含了其他头文件如bb.h,那么bb.h的任何改变都将导致所有包含了aa.h的代码被重新编译,在敏捷开发方式下,代码会被频繁构建,漫长的编译时间将极大的阻碍频繁构建。因此,我们倾向于减少包含头文件,尤其是在头文件中包含头文件,以控制改动代码后的编译时间。
合理的头文件划分体现了系统设计的思想,但是从编程规范的角度看,仍然有一些通用的方法,用来合理规划头文件。本章节介绍的一些方法,对于合理规划头文件会有一定的帮助。
原则1.1.1 头文件适合放置对外接口的声明,不适合放置实现,实现应放在定义文件中。
说明:头文件是模块(Module)或单元(Unit)的对外接口。变量定义应在.c中定义,在.h中仅声明,尽量不要使用全局变量作为接口,变量是程序内部实现细节,应通过函数接口的方式对外暴露。
个人理解如下:
h文件:包含需用头文件、对外类型和枚举、对外宏(常量)定义、对外变量声明(尽量不用)、对外函数声明。
c文件:包含同名头文件、内部类型和枚举、内部宏(常量)定义、内部变量定义、内部函数定义与实现。
延伸阅读材料:《C语言接口与实现》(David R. Hanson 著 傅蓉 周鹏 张昆琪 权威 译 机械工业出版社 2004年1月)(英文版: "C Interfaces and Implementations")
原则1.1.2 头文件应当职责单一。
说明:头文件过于复杂,依赖过于复杂是导致编译时间过长的主要原因。很多现有代码中头文件过大,职责过多,再加上循环依赖的问题,可能导致为了在.c中使用一个宏,而包含十几个头文件。
例如: 如下是某平台定义WORD类型的头文件:
#include <VXWORKS.H>
#include <STDIO.H>
#include <STDLIB.H>
#include <SYSLIB.H>
…
typedef unsigned short WORD;
…
这个头文件不但定义了基本数据类型WORD,还包含了stdio.h syslib.h等等不常用的头文件。如果工程中有10000个源文件,而其中100个源文件使用了stdio.h的printf,由于上述头文件的职责过于庞大,而WORD又是每一个文件必须包含的,从而导致stdio.h/syslib.h等可能被不必要的展开了9900次,大大增加了工程的编译时间。
规则1.1.1 每一个.c文件应有一个同名.h文件,用于声明需要对外公开的接口。
规则1.1.2 禁止头文件循环依赖。
说明:头文件循环依赖,是指a.h包含b.h,b.h包含c.h,c.h包含a.h之类。
规则1.1.3 头文件应当自包含。
说明:自包含是指任意一个头文件均可独立编译。如果a文件用到b文件内容,本应该a文件包含b.h头文件即可,但要包含b.h头文件前还要先包含c.h头文件才能工作的话,增添不必要的负担。
例如: a文件用到b文件内容
#include "c.h" //要想用b文件,a文件必须先包含c.h文件,这种情况就不是自包含。
#include "b.h" //a文件本应该包含b.h就可以。
规则1.1.4 .c/.h文件禁止包含用不到的头文件。
规则1.1.5 用#include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。
规则1.2.6 用#include“filename.h”格式来引用非标准库的头文件(编译器将从用户工作目录开始搜索)。
规则1.1.7 为防止头文件被重复引用,应用ifndef/define/endif 结构产生预处理。命名格式:FILENAME_H_。
说明:没有在宏最前面加上“_",是因为一般以"_"和”__"开头的标识符为系统保留或者标准库使用,在有些静态检查工具中,若全局可见的标识符以"_"开头会给出告警。后面加"_"是为了与程序用的宏定义区别。
例如:
#idndef LED_H_ //很明显这一部分也是为了防止重复引用
#define LED_H_
……
#endif /* LED_H_ */
规则1.1.8 禁止在头文件中定义变量。
说明:在头文件中定义变量,将会由于头文件被其他.c文件包含而导致变量重复定义。
规则1.1.9 禁止在extern "C"中包含头文件。(来自华为编程规范)
说明:在extern "C"中包含头文件,会导致extern "C"嵌套,Visual Studio对extern "C"嵌套层次有限制,嵌套层次太多会编译错误。在extern "C"中包含头文件,可能会导致被包含头文件的原有意图遭到破坏。
错误示例:
extern “C”
{
#include “xxx.h”
...
}
正确示例:
#include “xxx.h”
extern “C”
{
...
}
建议1.1.1 C程序头文件中加extern "C"。
说明:extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
示例: led头文件
#ifndef LED_H_ //很明显这一部分也是为了防止重复引用
#define LED_H_
#include"xxxx.h"
#ifdef __cplusplus //C++编译环境中(cpp文件定义了)定义了宏__cplusplus (plus plus就是"+ +"的意思)
extern "C"{ // 声明括号内是C语言代码,告诉C++编译器用C语言进行编译,这样C++就可以调用C头文件了
#endif
… //其他代码
#ifdef __cplusplus
}
#endif
#endif /* LED_H_ */
建议1.2.2 头文件中只存放“声明”而不存放“定义”。
建议1.2.3 不提倡使用全局变量,尽量不要在头文件中出现象 extern int value 这类声明。
建议1.2.4 一个模块通常包含多个.c文件,建议放在同一个目录下,目录名即为模块名。为方便外部使用者,建议每一个模块提供一个.h,文件名为目录名。
说明:需要注意的是,这个.h并不是简单的包含所有内部的.h,它是为了模块使用者的方便,对外整体提供的模块接口。
建议1.2.5 如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的.h,文件名为子模块名。
说明:降低接口使用者的编写难度。
建议1.2.6 同一产品统一包含头文件排列方式。
说明:常见的包含头文件排列方式:功能块排序、文件名升序、稳定度排序。建议以稳定度排序。
#include <C标准库头文件>
#include <C++标准库头文件>
#include "平台头文件" //MCU厂家、系统等头文件
#include "第三方头文件" //公司或第三方提供的成熟头文件
#include "自己写的基础全局头文件"
//base.h基础头文件,提供常用的数据类型、修饰符以及基础操作宏
//global.h包含了其他基础的应用的头文件,第一个文件包含在应用相关c文件中。
#include "自己写的工具头文件"
#include "本项目头文件"
#include "本文头文件"
1.2 定义文件
定义文件主要由三部分内容:定义文件注释;头文件的引用;程序的实现体(包括数据和代码)。
函数设计的精髓:编写整洁函数,同时把代码有效组织起来。代码要求简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。
代码的有效组织包括:逻辑层和物理层两个方面。逻辑层,主要是把不同功能的函数通过某种联系组织起来,主要关注模块间的接口,也就是模块的架构。物理层,无论使用什么样的目录或者名字空间等,需要把函数用一种标准的方法组织起来。例如:设计良好的目录结构、函数名字、文件组织等,这样可以方便查找。
原则1.2.1 一个函数仅完成一件功能。
说明:一个函数实现多个功能给开发、使用、维护都带来很大的困难。
原则1.2.2 重复代码应该尽可能提炼成函数。
说明:重复代码提炼成函数可以带来维护成本的降低。
规则1.2.1 避免函数过长,新增函数不超过50行(非空非注释行)。
说明:本规则仅对新增函数做要求,对已有函数修改时,建议不增加代码行。
规则1.2.2 避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。
说明:本规则仅对新增函数做要求,对已有的代码建议不增加嵌套层次。
规则1.2.3 设计高扇入,合理扇出(小于7)的函数。
说明:扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;而扇出过小,例如:总是1,表明函数的调用层次可能过多,这样不利于程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。通常函数比较合理的扇出(调度函数除外)通常是3~5。
规则1.2.4 可重入函数应避免使用共享变量;若使用则应通过互斥手段(关中断、信号量)对其加以保护。
说明:可重入函数是指可能被多个任务并发调用的函数。在多任务操作系统中,函数具有可重入性是多个任务可以共用此函数的必要条件。共享变量指的全局变量和static变量。
规则1.2.5 废弃代码(没有被调用的函数和变量)要及时清除。
建议1.2.1 函数不变参数使用const。
说明:不变的值更易于理解/跟踪和分析,把const作为默认选项,在编译时会对其进行检查,使代码更牢固/更安全。
建议1.2.2 函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用。
建议1.2.3 检查函数所有非参数输入的有效性,如数据文件、公共变量等。
说明:函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入参数之前,应进行有效性检查。
建议1.2.4 函数的参数个数不超过5个。
说明:函数的参数过多,会使得该函数易于受外部(其他部分的代码)变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。如果超过了5个建议拆分为不同函数。
建议1.2.5 除打印类函数外,不要使用可变长参函数。
说明:可变长参函数的处理过程比较复杂容易引入错误,而且性能也比较低,使用过多的可变长参函数将导致函数的维护难度大大增加。
建议1.2.6 在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字。
说明:如果一个函数只是在同一文件中的其他地方调用,那么就用static声明。使用static确保只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性。
第2章 注释规范
良好的注释可以提高程序的可读性、易防错性、易维护性等。
2.1 共性注释规范
原则2.1.1 优秀的代码可以自我解释,不通过注释即可轻易读懂。
说明:优秀的代码不写注释也可轻易读懂,注释无法把糟糕的代码变好,需要很多注释来解释的代码往往存在坏味道,需要重构。
原则2.1.2 注释的内容要清楚、明了,含义准确,防止注释二义性。
说明:错误的注释不但无益反而有害。
原则2.1.3 在代码的功能、意图层次上进行注释,提供有用、额外的信息。
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
示例:如下注释意义不大。
/* if receive_flag is TRUE */
if (receive_flag)
而如下的注释则给出了额外有用的信息。
/* if mtp receive a message from links */
if (receive_flag)
规则2.1.1 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
规则2.1.2 避免在注释中使用缩写,除非是通用或标准的缩写。
说明:在使用缩写时或之前,应对缩写进行必要的说明。
规则2.1.3 标识符命名中若使用特殊约定或缩写,则要有注释说明。
规则2.1.4 同一产品或项目组 注释格式统一。
规则2.1.5 注释应与其描述的代码相靠近。
规则2.1.6 注释应放在其代码上方相邻位置或右方,不可放在下面。如放于上方则需与其上面的代码用空行隔开,且与下方代码缩进相同。如放于代码后面则与代码空一格。
说明:可使程序排版整齐,并方便注释的阅读与理解。
建议2.1.1 避免在一行代码或表达式的中间插入注释。
说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
建议2.1.2 注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。
说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。
2.2 文档注释规范
规则2.2.1 对于要生成帮助文档的注释,采用工具可识别的注释格式。风格要统一。注释字符长度≤80。
说明:采用工具可识别的注释格式,例如Doxygen格式,方便工具导出注释形成帮助文档。(常见工具:Doxygen,JavaDoc,……)
示例:单行注释格式 1 采用风格:/** …… */ 或 ///…… 放在代码上行,表示注释下行代码
单行注释格式 2 采用风格:/**< …… */ 或 ///<…… 放在代码后面,表示注释前面代码
多行块注释格式 采用风格:/**
……
*/
规则2.2.2 项目、文件、函数、全局变量、全局常量、全局类型定义的注释格式采用工具可识别格式。
规则2.2.3 文件注释必须列出:版权说明、首页标签、工程名称、作者、工号、源码文档路径、项目详细描述、功能描述、用法描述、固件更新记录等。
示例:以doxygen格式为例(Doxygen格式常用关键字表,见附件1),注释风格如下:
/** @copyright Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
******************************************************************************
* @mainpage 无人机固件程序
* <table>
* <tr><th>Project <td>A600
* <tr><th>Author <td>缪某某(ID:123456)
* <tr><th>Source <td>D:\workspace\demo_project\examples\A600\A600-doxygen
* </table>
* @section 项目描述
* 该无人机是主要应用于......
*
* @section 功能描述
* -# 定高悬停
* -# 路径规划飞行
*
* @section 用法描述
* -# 用遥控器
*
* @section 固件更新记录
* <table>
* <tr><th>Date <th>H_Version <th>S_Version <th>Author <th>Description </tr>
* <tr><td>2018/08/17 <td>1.0 <td>S02010041808171 <td>lebo <td>创建初始版本 </tr>
* <tr><td>2019/06/24 <td>1.1 <td>S02010041906241 <td>lebo <td>
* -# 无
* </tr>
* </table>
******************************************************************************
*/
规则2.2.4 文件注释必须列出:版权说明、作者、工号、版本号、生成日期、概要内容、注解说明功能、注意事项、修改日志等。
示例:以doxygen格式为例,注释格式 风格如下:
/** @copyright Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
******************************************************************************
* @mainpage FreeRTOS实验
* <table>
* <tr><th>Project <td>FreeRTOSDemo
* <tr><th>Author <td>匠在江湖(ID:1234)
* <tr><th>Source <td>F:\BaiduNetdiskWorkspace\Work\FreeRTOSDemo
* </table>
* @section 项目描述
* - 类别1
* -# 情况1......
* -# 情况2......
* - 类别2
* -# 情况1......
* -# 情况2......
* @section 用法描述
*
* @section 固件更新记录
* <table>
* <tr><th>Date <th>H_Version <th>S_Version <th>Author(ID:xxxxxx) <th>Description </tr>
* <tr><td>2018/08/17 <td>1.0 <td>S02010041808171 <td>匠在江湖(ID:1234) <td>创建初始版本 </tr>
* </table>
******************************************************************************
*/
规则2.2.5 函数注释必须列出:概要、参数、返回值等。根据实际情况增加相关项。
示例1:以doxygen格式为例,注释格式 风格如下:
/**
******************************************************************************
* @brief 发送接收 模拟函数
* @param None
* @retval None
* @note
******************************************************************************
*/
示例2:
/**
******************************************************************************
* @brief xxx 函数
* @param None
* @return 函数执行结果
* - E_SUCCESS 成功
* - E_FAIL 失败
* @par 示例:
* @code
* int ret = register_all(&data, len, RT_TYPE_T1)
* @endcode
* @see :: xx表
******************************************************************************
*/
示例3:
/**
******************************************************************************
* @brief Register a User ADC Callback
* To be used instead of the weak predefined callback
* @param hadc Pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param CallbackID ID of the callback to be registered
* This parameter can be one of the following values:
* @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID
* @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion complete callback ID
* @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID
* @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID
* @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID
* @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
* @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
* @param pCallback pointer to the Callback function
* @retval HAL status
******************************************************************************
*/
示例4:
/**
******************************************************************************
* @brief Enables ADC, starts conversion of regular group and transfers result
* through DMA.
* Interruptions enabled in this function:
* - DMA transfer complete
* - DMA half transfer
* - overrun (if available)
* Each of these interruptions has its dedicated callback function.
* @note Case of multimode enabled (for devices with several ADCs): This
* function is for single-ADC mode only. For multimode, use the
* dedicated MultimodeStart function.
* @param hadc ADC handle
* @param pData The destination Buffer address.
* @param Length The length of data to be transferred from ADC peripheral to memory.
* @retval None
******************************************************************************
*/
建议2.2.6 类型定义列出:类型名称、概要等。根据实际情况增加相关项。
示例1:以doxygen格式为例,注释格式 风格如下:
/** @enum BoolTypeE
* @brief 布尔类型(逻辑型变量的定义符)
*/
typedef enum
{
E_FALSE = 0, //假(错误)
E_TRUE = !E_FALSE //真(正确)
}BoolTypeE;
示例2:以doxygen格式为例,注释格式 风格如下:
/** @struct info
* @brief 信息结构体 \n
* 定义存储的信息
*/
typedef struct 结构体名字
{
成员1, ///< 简要说明文字, 如果不加< 则会认为是成员2的注释
成员2, ///< 简要说明文字
成员3, ///< 简要说明文字
}结构体别名;
建议2.2.7 模块定义:模块组号 + 模块组名等。根据实际情况增加相关项。
示例1:纯定义。模块组号 MCU_Driver, 模块名 MCU Driver
/**
* @defgroup MCU_Driver MCU Driver
*/
或
/** @defgroup MCU_Driver MCU Driver */
示例2:定义 + 概要描述。
/** @defgroup MCU_Driver MCU Driver
* @brief
*/
示例3:定义 + 组范围。
/** @defgroup MCU_Driver MCU Driver
* @{
*/
......
/** @} end of MCU_Driver */
示例3:定义 + 组范围,加入到 MCU_Driver 模块组中,成为其子组。
/** @defgroup ADC_C_Includes ADC.C Includes
* @ingroup MCU_Driver
* @{
*/
#include "base.h"
#include "adc.h"
/** @} end of ADC_C_Includes */
2.3 C语言风格注释规范
规则2.3.1 不用生成注释文档 的注释, 采用编程语言标准注释格式。风格要统一。注释字符长度≤80。
示例:多行或单行注释格式 采用风格:/* …… */
只可单行注释格式 采用风格://……
建议2.3.1 包含头文件,类型定义,常量定义,宏定义,变量定义,函数定义与声明 要用注释划分模块,以便程序清晰易读。
建议2.3.2 定义文件中 包含头文件,类型定义,宏定义,变量定义,函数定义 注释风格。
/** @copyright Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
******************************************************************************
* @file mcu.c
* @brief
* @details
* @author 匠在江湖(ID:1234)
* @version V1.0
* @date 2014/05/08
******************************************************************************
* @attention
*
* @par 修改日志:
* <table>
* <tr><th>Date <th>Version <th>Author(ID:xxxxxx) <th>Description</tr>
* <tr><td>2014/05/08 <td>V1.0 <td>匠在江湖(ID:1234) <td>创建初始版本</tr>
* </table>
******************************************************************************
*/
/* Includes *******************************************************************/
……用户定义内容
/* Private typedef ************************************************************/
……用户定义内容
/* Private constants **********************************************************/
……用户定义内容
/* Private macro **************************************************************/
……用户定义内容
/* Private variables **********************************************************/
……用户定义内容
/* Private function prototypes ************************************************/
……用户定义内容
/**
******************************************************************************
* @brief MCU 初始化 函数
* @param None
* @return None
* @note
******************************************************************************
*/
void MCU_Init(void)
{
}
/********************************* END OF FILE ********************************/
建议2.3.3 头文件中 包含头文件,类型定义,常量定义,宏定义,函数声明 注释风格。
/** @copyright Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
******************************************************************************
* @file mcu.h
* @brief 与硬件相关的寄存器定义,包含头文件等。为了适用平台的转换
* @details
* @author 匠在江湖(ID:1234)
* @version V1.0
* @date 2014/05/08
******************************************************************************
* @attention
*
* @par 修改日志:
* <table>
* <tr><th>Date <th>Version <th>Author(ID:xxxxxx) <th>Description</tr>
* <tr><td>2014/05/08 <td>V1.0 <td>匠在江湖(ID:1234) <td>创建初始版本</tr>
* </table>
******************************************************************************
*/
#ifndef MCU_H_
#define MCU_H_
/* Includes *******************************************************************/
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "main.h"
#include "usart.h"
#include "base.h"
#include "iwdg.h"
#ifdef __cplusplus
extern "C"{
#endif
/* Exported types *************************************************************/
/* Exported constants *********************************************************/
/* Exported macro *************************************************************/
///NOP()
#define NOP() __NOP
///清看门狗
#define CLR_WDG() HAL_IWDG_Refresh(&hiwdg) //清看门狗
/* Exported functions *********************************************************/
void MCU_Init(void);
#ifdef __cplusplus
}
#endif
#endif /* MCU_H_ */
/********************************* END OF FILE ********************************/
建议2.3.4 在程序块的结束行右方加注释标记,以表明某程序块的结束。
说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。
示例:参见如下例子。
if (...)
{
// program code
while (index < MAX_INDEX)
{
// program code
} /* end of while (index < MAX_INDEX) */ // 指明该条while语句结束
// program code
} /* end of if (...)*/ // 指明是哪条if语句结束
第3章 排版规范
良好的排版可以提高程序的可读性、易防错性、易维护性等。
3.1 缩进与对齐 风格
规则3.1.1 程序块要采用缩进风格编写,缩进的空格数为4个。 不轻易使用TAB键。
说明:编辑器可用TAB键代替空格时方可使用,否则程序会因缩进不同而变乱。
规则3.1.2 程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。{ }之内的代码块在‘{’右边数格处左对齐。
说明:在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。
示例:
如下例子不符合规范。
for (...) {
... // program code
}
应如下书写。
for (...)
{
... // program code
}
3.2 空行
规则3.2.1 在每个类声明之后、每个函数定义结束之后都要加空行。
规则3.2.2 在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应
加空行分隔。
3.3 代码行
规则3.3.1 不允许把多个短语句写在一行中,即一行只写一条语句。
示例:
如下例子不符合规范。
rect.length = 0; rect.width = 0;
应如下书写
rect.length = 0;
rect.width = 0;
规则3.3.2 if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
示例:
如下例子不符合规范。
if (pUserCR == NULL) return;
应如下书写:
if (pUserCR == NULL)
{
return;
}
3.4 代码行内的空格
规则3.4.1 关键字之后要留空格。象const、virtual、inline、case 等关键字之后至少要留一个空格,否则无法辨析关键字。象if、for、while 等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。
规则3.4.2 函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。
规则3.4.3 ‘(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不留空格。
规则3.4.4 ‘,’之后要留空格,如Function(x, y, z)。如果‘;’不是一行的结束符号,其后要留空格,如for (initialization; condition; update)。
规则3.4.5 赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格。
规则3.4.6 一元操作符如“!”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空格。
规则3.4.7 像“[]”、“.”、“->”这类操作符前后不加空格。
建议3.4.1 对于表达式比较长的for 语句和if 语句,为了紧凑起见可以适当地去掉一些空格,如for (i=0; i<10; i++)和if ((a<=b) && (c<=d))
建议3.4.2 代码或注释结束后不要有多余的空格,防止空格后面有未知东西。
如下会存在未知隐患
应该如下
3.5 长行拆分
规则3.5.1 代码行不要过长,最长不超过80 个字符。否则眼睛看不过来,也不便于打印。
规则3.5.2 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。
示例:
if( (very_longer_variable1 >= very_longer_variable12)
&& (very_longer_variable3 <= very_longer_variable14)
&& (very_longer_variable5 <= very_longer_variable16))
{
dosomething();
}
第4章 标识符命名规范
规范的标识符命名可以提高程序的可读性、易防错性、易维护性等。标识符命名的种类繁多,各有优缺点。没有一种命名规则可以让所有的程序员赞同,程序设计教科书一般都不指定命名规则。命名规则对软件产品而言并不是“成败悠关”的事,我们不要化太多精力试图发明世界上最好的命名规则,而应当制定一种令大多数项目成员满意的命名规则,并在项目中贯彻实施。本章仅提出了大多都认可的规范,对于命名风格可依下面规范作为指导思想参考附件常见的风格。
4.1 共性命名规则
共性规则是被大多数程序员采纳的,我们应当在遵循这些共性规则的前提下,再扩充特定的规则。
原则4.1.1 标识符的命名要清晰、明了,有明确含义,使用完整的英文单词或大家基本可以理解的缩写,避免使人产生误解,让人快速理解你的代码很重要。
说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。
示例: temp缩写为tmp;flag缩写为flg;message缩写为msg。
规则4.1.1 产品/项目组内部应保持统一的命名风格。
说明:Unix like(小写下划线)和windows like(大小写混排)风格均有其支持者,产品应根据自己的部署平台,选择其中一种,并在产品内部保持一致。 不要使用大小写与下划线混排的方式,用作特殊标识如标识成员变量、全局变量或静态变量的m_、g_、s_,其后加上大小写混排的方式是允许的。
示例:Add_User不允许;add_user、AddUser、m_AddUser允许。
规则4.1.2 程序中不要出现仅靠大小写区分的相似的标识符。
示例:x 与 X 容易混淆。
建议4.1.1 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
示例: min/max ……
建议4.1.2 尽量避免名字中出现数字编号,除非逻辑上的确需要编号。
示例:
如下命名,使人产生疑惑。
#define _EXAMPLE_0_TEST_
应改为有意义的单词命名
#define _EXAMPLE_UNIT_TEST_
建议4.1.3 标识符前不应添加模块、项目、产品、部门的名称作为前缀。
说明:很多已有代码中已经习惯在文件名中增加模块名,这种写法类似匈牙利命名法,导致文件名不可读,并且带来如下问题:第一眼看到的是模块名,而不是真正的文件功能,阻碍阅读;文件名太长;文件名和模块绑定,不利于维护和移植。若foo.c进行重构后,从a模块挪到b模块,若foo.c中有模块名,则需要将文件名从a_module_foo.c改为b_module_foo.c 。
建议4.1.4 平台/驱动等适配代码的标识符命名风格保持和平台/驱动一致。
说明:涉及到外购芯片以及配套的驱动,这部分的代码变动(包括为产品做适配的新增代码),应该保持原有的风格。
建议4.1.5 重构/修改部分代码时,应保持和原有代码的命名风格一致。
说明:根据源代码现有的风格继续编写代码,有利于保持总体一致。
4.2 文件命名规则
建议4.2.1 文件命名统一采用小写字符。
说明:因为不同系统对文件名大小写处理会不同(如MS的DOS、Windows系统不区分大小写,但是Linux系统则区分),所以代码文件命名建议统一采用全小写字母命名。
4.3 变量命名规则
规则4.3.1 全局变量应增加“g_”前缀。
规则4.3.2 静态变量应增加“s_”前缀。
说明:全局变量十分危险,增加前缀更加醒目,名字丑陋,促使开发人员小心和少使用。从根本上来说,尽量不使用全局变量。
规则4.3.3 禁止使用单个字符命名变量,但i、j、k作局部循环变量是允许的。
建议4.3.1 变量的名字应当使用“名词”或者“形容词+名词”。
建议4.3.2 全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
4.4 函数命名规则
建议4.4.1 函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构。
建议4.4.2 函数指针除了前缀,其他按照函数的命名规则命名。
4.5 宏的命名规则
规则4.4.1 对于数值或者字符串等常量的定义,建议采用全大写字母,单词之间加下划线的方式命名(枚举同样建议使用此方式定义)。
规则4.4.2 除了编译开关/头文件等特殊应用,应避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。
说明:一般来说,“_”开头、结尾的宏都是一些内部的定义,ISO/IEC 9899(俗称C99)中有描述。
第5章 变量
原则5.1.1 一个变量只有一个功能,不能把一个变量作多种用途。
原则5.1.2 结构单一,不要设计面面俱到的结构。
原则5.1.3 不用或者少用全局变量。
规则5.1.1 防止局部变量与全局变量重名。
规则5.1.2 通讯过程中使用的结构,必须注意字节序。
规则5.1.3 严禁使用未经初始化的变量作为右值
说明:在首次使用前初始化变量,初始化的地方离使用的地方越近越好,可以有效避免未初始化错误。
建议5.1.1 构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问全局变量,防止多个模块或函数都可以修改、创建同一全局变量的现象。
说明:降低全局变量耦合度。
建议5.1.2 使用面向接口编程思想,通过API访问数据:如果本模块的数据需要对外部模块开放,应提供接口函数来设置、获取,同时注意注意全局数据的访问互斥。
建议5.1.3 明确全局变量初始化的顺序,避免跨模块初始化的依赖。
建议5.1.4 尽量减少没有必要的数据类型默认转换或强制转换。
第6章 常量、宏
规则6.1.1 用宏定义表达式时,要使用完备的括号。
说明:因为宏只是简单的代码替换,不会计算,存在一定的风险。
规则6.1.2 将宏定义的多条表达式放在大括号中。
说明:更好的方法是多条语句写成do while(0)的方式。
示例:
看下面的语句,只有宏的第一条表达式被执行。
#define FOO(x) \
printf("arg is %d\n", x); \
do_something_useful(x);
为了说明问题,下面for语句的书写稍不符规范
for (blah = 1; blah < 10; blah++)
FOO(blah)
用大括号定义的方式可以解决上面的问题:
#define FOO(x) { \
printf("arg is %s\n", x); \
do_something_useful(x); \
}
但是如果有人这样调用:
if (condition == 1)
FOO(10);
else
FOO(20);
那么这个宏还是不能正常使用,所以必须这样定义才能避免各种问题:
#define FOO(x) do{ \
printf("arg is %s\n", x); \
do_something_useful(x); \
}while(0)
用do-while(0)方式定义宏,完全不用担心使用者如何使用宏,也不用给使用者加什么约束。
规则6.1.3 使用宏时,不允许参数发生变化。
示例:
如下用法可能导致错误。
#define SQUARE(a) ((a)*(a))
int a=5;
int b;
b= SQUARE(a++);//结果:a=7,即执行了两次增。
正确用法:
b= SQUARE(a++);
a++;//结果:a=6,即执行了一次增。
同时也建议即使函数调用,也不要在参数中做变量变化操作,因为可能引用的接口函数,在某个版本升级后,变成了一个兼容老版本所做的一个宏,结果可能不可预知。
规则6.1.4 不允许直接使用魔鬼数字(没有具体含义的数字,字符串)。
说明:魔鬼数字含义不明确,维护难。使用常量定义魔鬼数字。0为特殊字符,没有歧义时,不用特别定义。
建议6.1.1 除非必要,应尽可能使用函数代替宏。
建议6.1.2 常量建议使用const定义代替宏。
建议6.1.3 宏定义中尽量不使用return、goto、continue、break等改变程序流程的语句。
建议6.1.4 常量后加后缀。32位常量要加ul。
U 或 u 无符号数
L 或 l 长整型
F 或 f 浮点数
第7章 数据类型
规则7.1.1 signed char和unsigned char用于数字型数据;char用于字符型数据。
说明:单纯的char所能接收的操作只有“ =、==、!= ”。
规则7.1.2 位域只能被定义为signed int和unsigned int。
说明:由于行为未被定义,所以不允许位域使用enum、short、char类型。
建议7.1.1 应使用指示了 大小 和 符号 的typedef以替代基本数据类型。
说明:不使用基本类型 char、int、short、long、float、double,而使用typedef创建别名体现大小和符号。
例如:32位计算机
typedef char char_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
typedef float float32_t;
typedef double float64_t;
附件1 常用单词缩写(英文)(元音:aeiou)
全词 | 缩词/简写 | 中译 | 全词 | 缩词/简写 | 中译 |
指令内核相关类 | |||||
source | src | 源头 | default | def | 默认 |
destination | dst或des | 目的地,目标 | define | def | 定义 |
operator | optr | 操作符 | macro | mcr | 宏 |
operand | opnd | 操作数 | return | ret | 返回 |
offset | ofs | 偏移 | assemble | asm | 汇编 |
clear | clr | 清除 | interrupt | intr | 中断 |
move | mov | 移动 | priority | prio | 优先级 |
instruction | instr | 指令 | vector | vect | 向量 |
变量内存相关类 | |||||
temperature | temper | 温度 | address | addr | 地址 |
temporary | tmp | 临时 | pointer | ptr | 指针 |
counter | ctr | 计数器 | buffer | buf | 缓冲区 |
count | cnt | 计数 | stack | stk | 堆 |
flag | flg | 旗帜、标识 | memory | mem | 内存 |
parameter | par | 参数 | storage | stg | 存储器 |
argument | arg | 参数 | block | blk | 块 |
variable | var | 变量 | allocate | alloc | 分配 |
array | arr | 数组 | object | obj | 对象 |
string | str | 字符串 | |||
character | char | 字符 | |||
数学计算相关类 | |||||
increment | inc | 增加 | average | avg | 平均数 |
decrease | dec | 减少 | summation | sum | 求和;总和 |
addition | add | 增加;加法 | calculate | calc | 计算 |
subtraction | sub | 减少,减法 | total | tot | 总计 |
multiplication | mul | 乘法 | magnitude | mag | 巨大 |
division | div | 除法;除以 | maximum | max | 最大 |
proportion | kp | 比例 | minimum | min | 最小 |
integral | ki | 积分 | middle | mid | 中间 |
differential | kd | 微分 | equivalent | equiv | 相等的 |
absolute | abs | 绝对值 | greater equal | ge | 大于等于 |
algorithm | algo | 算法 | greater than | gt | 大于 |
exponent | expo | 指数 | less equal | le | 小于等于 |
recur | recu | 递归 | less than | lt | 小于 |
limit | lim | 限制 | quarter | quar | 四分之一 |
mantissa | mant | 尾数 | scale | scal | 比例 |
fraction | fract | 小数 | double | dbl | 两倍 |
digit | dig | 数字 | |||
number | num | 数字;数量 | |||
value | val | 值 | |||
其他计算相关类 | |||||
reference | ref | 引用,参考 | between | btw | 之间 |
compare | cmp | 比较 | interval | intvl | 间隔 |
different | diff | 对比 | different | diff | 区别 |
optimization | opt | 最优化 | error | err | 错误 |
degree | deg | 度数,程度 | exception | exc | 异常 |
full | ful | 全量 | |||
multiplex | mux | 多路复用 | result | rslt | 结果 |
overflow | ovf | 溢出 | complete | comp | 完成 |
check | chk | 检查,核对 | success | succ | 成功 |
test | tst | 测试 | error | err | 错误 |
detect | 检测,识别 | ||||
measure | meas | 测量 | |||
sample | smp | 样本 | |||
make | mk | 制造 | |||
时间顺序相关类 | |||||
timer | tmr或tim | 定时器 | new | 新的 | |
time | tm | 时间 | old | 老的;旧的 | |
second | sec | 秒、第二 | now | 现在;目前 | |
minute | min | 分钟 | current | cur | 当前 |
hour | hr | 小时 | previous | prev | 先前的 |
day | 天 | delay | dly | 延迟 | |
month | mth | 月 | expiration | expi | 过期 |
year | 年 | next | nex | 下一个 | |
period | perd | 时期 | |||
timestamp | ts | 时间戳 | |||
timeout | to | 超时 | |||
age | 年龄 | ||||
结构方向相关类 | |||||
positon | pos | 位置 | origin | org | 起源,原点 |
coordinates | coord | 坐标系 | point | pt | 点 |
row | 行 | rect | rc | 矩形 | |
column | col | 列 | rectangle | rect | 长方形 |
vertical | vert/v | 垂直 | cylinder | cyl | 圆柱体 |
horizontal | hori/h | 水平的 | length | len | 长度 |
dimension | dim | 维度 | high | hi | 高度;高的 |
permutation | perm | 排列 | invert | invt | 颠倒 |
信息相关类 | |||||
information | info | 信息 | command | cmd | 命令 |
communication | comu | 通信 | config | conf | 配置 |
message | msg | 消息;信息 | request | req | 请求 |
packet | pkt | 信息包 | acknowledge | ack | 承认;应答 |
package | pkg | 包 | answer | ans | 回答 |
protocol | proto | 协议 | response | rsp | 响应 |
stream | stm | 流 | |||
header | hdr | 头 | |||
index | idx | 索引 | decode | deco | 解码 |
frame | frm | 帧率;框架 | encode | enc | 编码 |
clock | clok | 时钟 | coding | 译码;编码 | |
receive | recv | 接收 | authentication | auth | 校验 |
send | send | 发送 | authentication code | authcode | 校验码 |
context | ctx | 上下文 | unknown | unk | 未知 |
connect | con | 连接 | extension | ext | 扩展 |
ethernet | eth | 以太网 | expand | expa | 扩展 |
mailbox | mbox | 邮箱 | field | fld | 字段 |
mask | msk | 掩码 | identifier | id | 标识符 |
decode | deco | 解码 | |||
encode | enc | 编码 | |||
计算机动作操作类 | |||||
construct | cons | 构建 | select | sel | 选择 |
control | ctl | 控制 | delete | del | 删除 |
execute | exec | 执行 | insert | ins | 插入 |
register | reg | 注册 | copy | cpy | 复制 |
click | clk | 点击 | paste | 粘贴 | |
back | bk | 后退 | cut | 剪切 | |
disable | dis | 使失效 | | Prn/prt | 打印 |
enable | en | 使能 | input | in | 输入 |
effective | eff | 有效的 | output | out | 输出 |
invalid | inv | 无效的 | lock | lck | 上锁 |
logic | lgc | 逻辑的 | unlock | unlk | 解锁 |
read | r | 读 | scan | sca | 扫描 |
write | w | 写 | search | srch | 搜索 |
计算机专业名称类 | |||||
iteration | itr | 迭代;反复;重复 | initialization | init | 初始化 |
version | ver | 版本 | program | prg | 程序 |
password | psw | 密码 | system | sys | 系统 |
permission | perms | 许可 | android | adr | 安卓操作系统 |
device | dev | 设备 | application | app | 应用程序 |
administrator | adm | 管理员 | driver | drv | 驱动 |
manager | mgr | 管理者,管理器 | update | upd | 更新 |
standard | std | 标准 | upgrade | upg | 升级 |
library | lib | 静态库 | environment | env | 运行环境 |
database | db | 数据库 | process | proc | 进程 |
dynamic | dyna | 动态 | ready | rdy | 就绪 |
synchronization | sync | 同步 | suspend | susp | 挂起 |
asynchronization | asyn | 异步 | status | sts | 状态 |
link | lnk | 链接 | signal | sig | 信号 |
server | svr | 服务 | semaphore | sem | 信号量 |
executable file | exe | 可执行文件 | scheduler | scher | 调度器 |
sequence | seq | 序列 | task | tsk | 任务 |
serialize | seri | 序列化 | statistic | stat | 统计 |
virus | vir | 病毒 | process | proc | 进程 |
ready | rdy | 就绪 | |||
文档图片类 | |||||
directory | dir | 目录 | bitmap | bmp | 位图纹理 |
list | lst | 列表 | image | img | 图像 |
log | log | 日志 | picture | pic | 图片 |
document | doc | 文档 | color | clr | 颜色 |
text | txt | 文本 | record | rcd | 记录 |
table | tab或tbl | 表格 | dictionary | dict | 词典、字典 |
manual | man | 手册 | |||
specification | spec | 说明 | |||
软件界面名称类 | |||||
screen | scr | 屏幕 | button | btn | 按钮 |
display | disp | 显示 | component | com | 组件(多用于ui组件目录命名) |
util | 工具 | window | wnd | 窗口 | |
attribute | attr | 属性 | dialog | dlg | 对话框 |
feature | fea | 特征 | cursor | csr | 光标 |
bottom | btm | 底部 | markdown | md | 文本标记语言 |
descriptor | desc | 描述符 | |||
visible | vis | 可见的 | |||
电气相关类 | |||||
frequency | freq | 频率 | poweron | pwron | 上电 |
voltage | vol | 电压 | back electromotive force | BEF | 反电动势 |
current | cur | 电流 | speed | spd | 速度 |
power | pwr | 功率/电源 | electric | elec | 电子的 |
trigger | trig | 触发器 | |||
threshold | thold | 阈值 | |||
switch | sw | 开关 | |||
toggle | tgl | 切换 | |||
其他类 | |||||
resource | res | 资源 | prefix | pre | 前缀 |
region | rgn | 区域、领域 | reactive | react | 有反应的 |
group | grp | 组 | recall | rcl | 召回 |
assemble | asm | 集合 | release | rel | 发布 |
repeat | rpt | 重复 | |||
action | act | 动作 | duplicate | dup | 重复 |
common | comm | 通用 | repository | repo | 仓库 |
dependency | dep | 依赖 | reserve | resv | 保留 |
debug | dbg | 调试 | reset | rst | 重置 |
direct | dirt | 直接的 | resume | resu | 重新开始 |
engine | eng | 引擎 | reverse | revs | 反转 |
experiment | exp | 实验 | schedule | sch | 计划 |
exposure | expo | 曝光 | section | sect | 节 |
generate | gen | 产生 | segment | seg | 段 |
handler | 处理者 | strategy | stra | 策略 | |
marshal | mar | 序列化 | change | chg | 改变 |
unmarshal | unmar | 反序列化 | convert | conv | 转换 |
deserialize | dese | 反序列化 | translate | tran | 翻译,转换 |
manufacturer | mft | 制造商 | |||
positive | posi | 积极的 | |||
negative | neg | 消极的 | |||
neutral | neut | 中立 | |||
quality | qlty | 质量 | |||
properties | prop | 性能 | |||
performance | perf | 性能 | |||
product | prod | 产品 | |||
profile | pf | 用户画像 | |||
project | proj | 项目 | |||
protect | prot | 保护 | |||
proxy | prx | 代理 | |||
public | pub | 公共的 | |||
附件2 常用反义词组(英文)
词 | 反义词 | 中译 | 词 | 反义词 | 中译 |
add | remove | 添加/移除 | min | max | 最小/最大 |
add | delete | 添加/删除 | old | new | 旧/新 |
begin | end | 开始/最后 | start | stop | 开始/停止 |
create | destroy | 创建/破坏 | next | previous | 下个/以前的 |
insert | delete | 插入/删除 | source | target | 源头/目标 |
first | last | 第一/最后 | show | hide | 显示/隐藏 |
get | release | 获得/释放 | send | receive | 发送/接收 |
put | get | 放下/获得 | source | destination | 源头/目的 |
increment | decrement | 增加/减少 | cut | paste | 剪切/粘贴 |
lock | unlock | 上锁/解锁 | up | down | 上/下 |
open | close | 打开/关闭 | top | btm | 顶部/底部 |
附件3 Doxygen格式常用关键字表
Doxygen注释关键字(更多内容详见Doxygen手册) | ||
注释命令 | 标签名 | 功能描述 |
特殊功能 | ||
\li | 生成一个黑心圆. | |
- |
| 生成一个黑心圆. |
-# |
| 指定按顺序标记。 |
:: |
| 指定连接函数功能。(注:空格和“:”有连接功能,但建议还是使用”::”。只对函数有用。) |
文件信息 | ||
@mainpage | 首页 | 描述内容,并将注释提到首页标签中去 |
@copyright | 版权所有 |
|
@file |
| 文件名,可以默认为空,DoxyGen会自己加 |
@details | 详细描述 | |
@author | 作者 |
|
@version | 版本 |
|
@date | 日期 |
|
@remarks | 备注 |
|
@par | 自定义名 | 开始一个段落,段落名称描述由你自己指定 |
@section | 自定义名 | 开始一个段落,段落名称描述由你自己指定 |
@name | 自定义名 | 分组名强制给注释段给定自定义名称,自动列在注释前,比@brief还前。 |
@since {text} | 自从 | 通常用来说明从什么版本、时间写此部分代码。 |
@todo { things to be done } | 待办事项: | 对将要做的事情进行注释,链接到所有TODO 汇总的TODO 列表 |
模块信息 | ||
@include | 包含文件 | |
@var | 变量 | 对模块 变量 进行标注,Doxygen会在该变量处产生一个链接,归纳到变量列表中去。 |
@typedef | 对模块 变量类型 进行标注 | |
@enum | 枚举 | 对模块 枚举 进行标注,Doxygen会在该枚举处产生一个链接,归纳到枚举列表中去。 |
@struct | 结构体 | 对模块 结构体 进行标注,Doxygen会在该枚举处产生一个链接,归纳到结构体列表中去。 |
@class | 类 | 引用某个类 进行标注,格式:@class <name> [<header-file>] [<header-name>] eg:@class CTest "inc/class.h" |
@defgroup [gTag] [gName] | [gName] | 定义模块组 |
@addtogroup [gTag] |
| 添加到一个模块组 |
@ingroup [gTag] |
| 加入到一个模块组 |
@{ |
| 模块开始 |
@} |
| 模块结束 |
@code |
| 在注释中开始说明一段代码,直到@endcode命令。 |
@endcode |
| 在注释中代码段的结束。 |
@pre { description of the precondition } | 前置条件 | 用来说明代码项的前提条件。 |
@post { description of the postcondition } | 后置条件 | 用来说明代码项之后的使用条件。 |
@relates <name> | 通常用来把非成员函数的注释文档包含在类的说明文档中。 | |
函数信息 | ||
@fn | 函数说明 | |
@param | 参数 | 主要用于函数说明中,后面接参数的名字,然后再接关于该参数的说明。标记一个参数的意义 |
@prg | 列表说明参数信息 | |
@return | 返回 | 描述返回值情况eg: @return 本函数返回执行结果,若成功则返回TRUE,否则返回FLASE |
@retval | 返回值 | 描述返回值类型 eg: @retval NULL 空字符串。@retval !NULL 非空字符串 |
@note | 注解 | 开始一个段落,用来描述一些注意事项 |
提醒信息 | ||
@brief |
| 概要信息,简短描述,自动列在注释前。 |
@see {comment with reference to other items } | 参见 | 一段包含其他部分引用的注释,中间包含对其他代码项的标识符,自动产生对其标识符的引用链接。 |
@attention | 注意 |
|
@bug | Bug: | 缺陷,链接到所有缺陷汇总的缺陷列表 |
@warning {warning message } | 警告 | 一些需要注意的事情 |
@sa | 参考资料 | |
@exception <exception-object> {exception description} | 异常 | 可能产生的异常描述 eg: @exception 本函数执行可能会产生超出范围的异常 |
@deprecated | 弃用: | 已废弃函数,链接到 待办事项列表 |
附件4 标识符命名个人风格
标识符命名个人风格 | |||
标识符 | 其他环境 | FreeRTOS环境 | uCos-II环境 |
文件夹名 | 帕斯卡(大驼峰) | 帕斯卡(大驼峰) | 帕斯卡(大驼峰) |
文件名 | 下划线 | 下划线 | 下划线 |
变量名 | 骆驼(小驼峰) 结构体变量加前缀st_ 联合体变量加前缀ut_ 枚举变量加前缀et_ | 匈牙利 (有修改) | 下划线 |
常量/宏名 | 全大写 | 小写(文件名部分)+大写 | 全大写 |
函数名 | 帕斯卡(大驼峰) | 匈牙利 (有修改) | 帕斯卡(大驼峰) |
方法名 | 帕斯卡(大驼峰) | ||
接口名 | 帕斯卡(大驼峰) | ||
类名 | 帕斯卡(大驼峰) | ||
结构体类型名 | 帕斯卡(大驼峰) | ||
联合体类型名 | 帕斯卡(大驼峰) | ||
枚举类型名 | 帕斯卡(大驼峰) |
附件5 常见标识符命名风格种类
常见 编程标识符命名风格 种类 | |||||
类别 | 别称 | 命名法逻辑 特点 | 举例 | 优缺点 | 常见应用场合 |
帕斯卡 | 大驼峰 | 大小写混排,每个单词的首字母大写。 | void GetKey(void); | 函数库和Jave平台下居多。 | |
骆驼 | 小驼峰 | 大小写混排,每个单词的首字母大写,第一个单词的首字母小写。 | void getKey(void); | 面向对象语言(Java、C#)变量、方法常用。 | |
匈牙利 | 类同 | 大小写混排,每个单词的首字母大写,第一个单词的首字母小写,小写字母用来表明标识符的属性、类型等。 | void vGetKey(void); | 优点:可读性很强,清晰。 | 常见于Windows。 |
下划线 | 全小写,以 下划线 分割逻辑断点。上面是以大写字母为逻辑断点。 | void get_key(void); | 常见于Linux内核,C++标准库,Boost以及Ruby,Rust等语言。C、Python变量常用。 |