嵌入式C语言代码规范
C语言代码规范
参考安富莱C语言编码规范
1.文件与目录
1、文件及目录的命名规定可用的字符集是[A-Z;a-z;0-9;._-]。
2、源文件名后缀用小写字母 .c 和.h。
3、文件的命名要准确清晰地表达其内容,同时文件名应该精练,防止文件名过长而造成使用不便。在文件名中可以适当地使用缩写。
以下提供两种命名方式以供参考:
(1)各程序模块的文件命名开头 2 个消协字母代表本模块的功能:
如:主控程序为 mpMain.c,mpDisp.c …
(2)不写模块功能标识:
如:主控程序为 Main.c,Disp.c …
4、一个软件包或一个逻辑组件的所有头文件和源文件建议放在一个单独的目录下,这样有利于查找并使用相关的文件,有利于简化一些编译工具的设置。
5、对于整个项目需要的公共头文件,应存放在一个单独的目录下(例如:myProject/include)下,可避免其他编写人引用时目录太过分散的问题。
6、对于源码文件中的段落安排,我们建议按如下的顺序排列:
a. 文件头注释
b. 防止重复引用头文件的设置
c. #include 部分
d. #define 部分
e. enum 常量声明
f. 类型声明和定义,包括 struct、union、typedef 等
g. 全局变量声明
h. 文件级变量声明
i. 全局或文件级函数声明
j. 函数实现。按函数声明的顺序排列
k. 文件尾注释
7、在引用头文件时,使用 <> 来引用预定义或者特定目录的头文件,使用 “” 来引用当前目录或者路径相对于当前目录的头文件。
1 #include <file.h>
执行这条指令时,它会在系统目录中去查找 file.h 文件。在此条码命令中,不会去当前路径和附加路径中查找文件。2 #include "file.h"
执行这条指令时,它首先会搜索附加路径,如果没有则会搜索系统路径,如果还没有则会去搜索当前路径。
8、为了防止头文件被重复引用,应当用 ifndef/define/endif 结构产生预处理块。
#ifndef __DISP_H /* 文件名前名加两个下划线“__”,后面加 “_H”
#define __DISP_H
...
...
#endif /* disp.h*/
9、头文件中只存放“声明”而不存放“定义”,通过这种方式可以避免重复定义。如果其它模块需要引用全局变量 g_temp, 只需要在文件开头包含 disp.h
#ifndef __DISP_H /* 文件名前名加两个下划线“__”,后面加 “_H”
#define __DISP_H
/** 全局变量声明 */
extern uint32_t g_temp;
#endif /* disp.h*/
#include "disp.h"
/** 全局变量定义 */
uint32_t g_temp = 0;
2.排版
1、程序块要采用缩进风格编写,缩进的空格数为 4 个。尽量用空格,在不同环境下Tab键代表的空格可能不同,导致排版混乱。
2、相对独立的程序块之间、变量说明之后必须加空行增加可读性、变量最好在使用时在定义。
3、当一行太长时,可以按操作符处划分新行,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
ANO_DT_send_int16((short)(sin(data1/180.0f * PI) * 100),(short)(sin(data2/180.0f * PI) * 100),(short)(sin(data3/180.0f * PI) * 100),(short)(sin(data4/180.0f * PI) * 100), (short)(sin(data5/180.0f * PI) * 100), 0, 0,0);
4、不允许把多个短语句写在一行中,即一行只写一条语句。
5、程序块的分界符(如大括号‘{’和‘}’ )应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及 if、for、do、while、switch、case 语句中的程序都要采用如上的缩进方式。对于与规则不一致的现存代码,应优先保证同一模块中的风格一致性。
for (...) { <---- 不规范的写法... /* program code */}for (...){ <---- 规范的写法... /* program code */}if (...){ <---- 不规范的写法... /* program code */}if (...){ <---- 规范的写法... /* program code */}
6、在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。
说明:采用这种松散方式编写代码的目的是使代码更加清晰。
由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在 C语言中括号已经是最清晰的标志了。
在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。
示例:
(1)逗号、分号只在后面加空格。
int_32 a, b, c;
(2)比较操作符,赋值操作符"="、 “+=”,算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"<<"、"^"等双目操作符的前后加空格。
if (current_time >= MAX_TIME_VALUE)a = b + c;a *= 2;a = b ^ 2;
(3)"!"、"~"、"++"、"–"、"&"(地址运算符)等单目操作符前后不加空格。
*p = 'a'; /* 内容操作"*"与内容之间 */flag = !isEmpty; /* 非操作"!"与内容之间 */p = &mem; /* 地址操作"&" 与内容之间 */i++; /* "++","--"与内容之间 */
(4)"->"、"."前后不加空格。
p->id = pid; /* "->"指针前后不加空格 */
3.注释
1、一般情况下,源程序有效注释量必须在 20%以上。
说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。
2、在文件的开始部分,应该给出关于文件版权、内容简介、修改历史等项目的说明。
具体的格式请参见如下的说明。在创建代码和每次更新代码时,都必须在文件的历史记录中标注版本号、日期、作者、更改说明等项目。
/*!* @file LQ_ADC.c** @brief ADC驱动文件** @company 北京龙邱智能科技** @author LQ-005** @note 无** @version V1.1 2019/12/06 优化注释 Doxygen** @par URL http://shop36265907.taobao.com* http://www.lqist.cn** @date 2019/10/18 星期五*/
3、对于函数,在函数实现之前,应该给出和函数的实现相关的足够而精练的注释信息。内容包括本函数功能介绍,调用的变量、常量说明,形参说明,特别是全局、全程或静态变量(慎用静态变量),要求对其初值,调用后的预期值作详细的阐述。具体的书写格式和包含的各项内容请参见如下的例子。
/*!* @brief ADC通道初始化** @param channel : ADC通道 LQ_ADC.h中的一个枚举体 * @param bit : ADC通道精度 LQ_ADC.h中的一个枚举体 ** @return 无** @note 读取ADC之前一定要调用该函数对ADC通道进行初始化** @see ADC_InitConfig(ADC0CH0_P0_10, ADC_12bit); //初始化ADC通道0 P0_10** @date 2019/10/21 星期一*/
void ADC_InitConfig(ADCn_Ch channel, ADC_nbit bit)
对于宏定
/*! CTIMER 最大占空比 可自行修改 */
#define CMTER_PWM_MAX 10000
结构体、枚举体注释
/** * @brief CTIMER模块 脉冲计数通道* @note CTIMER 模块 脉冲捕获通道 * @note CTIMER 模块的输入管脚并不是直接CTIMER连接的 而是通过INPUTMUX模块连接的* @note CTIMER计数器 --- INPUTMUX输入多路复用模块17路通道 ---- 芯片外部管脚* @note 简单说 就是CTIMER的捕获通道每个都可以与 INPUTMUX模块的17路通道相链接* @note INPUTMUX模块的17路通道相链接的管脚如下*/
typedef enum
{CTInput0_P0_1 = 0x0000 + 1, CTInput0_P0_13 = 0x0000 + 2, /*!< INPUTMUX—CTIMER 输入通道0管脚 */ CTInput1_P0_14 = 0x0100 + 1, CTInput1_P0_2 = 0x0100 + 2, /*!< INPUTMUX—CTIMER 输入通道1管脚 */ CTInput2_P1_0 = 0x0200 + 1, CTInput2_P1_28 = 0x0200 + 2, /*!< INPUTMUX—CTIMER 输入通道2管脚 */ CTInput3_P1_1 = 0x0300 + 1, CTInput3_P1_26 = 0x0300 + 2, /*!< INPUTMUX—CTIMER 输入通道3管脚 */ CTInput4_P1_9 = 0x0400 + 1, CTInput4_P0_16 = 0x0400 + 2, /*!< INPUTMUX—CTIMER 输入通道4管脚 */ CTInput5_P1_11 = 0x0500 + 1, /*!< INPUTMUX—CTIMER 输入通道5管脚 */ CTInput6_P1_13 = 0x0600 + 1, /*!< INPUTMUX—CTIMER 输入通道6管脚 */ CTInput7_P1_15 = 0x0700 + 1, /*!< INPUTMUX—CTIMER 输入通道7管脚 */ CTInput8_P0_24 = 0x0800 + 1, /*!< INPUTMUX—CTIMER 输入通道8管脚 */ CTInput9_P0_25 = 0x0900 + 1, /*!< INPUTMUX—CTIMER 输入通道9管脚 */ CTInput10_P0_10= 0x0A00 + 1, /*!< INPUTMUX—CTIMER 输入通道10管脚 */ CTInput11_P0_28= 0x0B00 + 1, /*!< INPUTMUX—CTIMER 输入通道11管脚 */ CTInput12_P0_4 = 0x0C00 + 1, /*!< INPUTMUX—CTIMER 输入通道12管脚 */ CTInput13_P0_6 = 0x0D00 + 1, /*!< INPUTMUX—CTIMER 输入通道13管脚 */ CTInput14_P1_20= 0x0E00 + 1, CTInput14_P0_26= 0x0E00 + 2, /*!< INPUTMUX—CTIMER 输入通道14管脚 */ CTInput15_P0_20= 0x0F00 + 1, CTInput15_P0_22= 0x0F00 + 2, /*!< INPUTMUX—CTIMER 输入通道15管脚 */ CTInput16_P0_15= 0x1000 + 1, /*!< INPUTMUX—CTIMER 输入通道16管脚 */ } CTIMER_InputChannel_t;
全局变量
/** DMA link传输描述符 */
extern dma_descriptor_t s_dma_descriptor_table0[];
注释应严格按以上格式进行注释,方便日后使用Doxygen生成帮助API文档
4、边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
5、注释的内容要清楚、明了,含义准确,防止注释二义性。
说明:错误的注释不但无益反而有害。注释主要阐述代码做了什么(What),或者如果有必要的话,阐述为什么要这么做(Why),注释并不是用来阐述它究竟是如何实现算法(How)的。
6、普通注释格式尽量统一,建议使用“/* …… */”注释在代码上方, C++注释“//”并不被所有 C 编译器支持。
7、注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能非常流利准确的用英文表达。
8、标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
9、命名中若使用特殊约定或缩写,则要有注释说明。
10、自己特有的命名风格,要自始至终保持一致,不可来回变化。
11、 对于变量命名,禁止取单个字符(如 i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但 i、j、k 作局部循环变量是允许的。
12、 除了编译开关/头文件等特殊应用,应避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。
13、除非必要,不要用数字或较奇怪的字符来定义标识符。
4.可读性
1、注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。
word = (high << 8) | low;
if ((a | b) && (a & c))
if ((a | b) < (c & d))
2、避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替。
if (Trunk[index].trunk_state == 0) <---- 不规范的写法,应使用有意义的标识
{Trunk[index].trunk_state = 1; <---- 不规范的写法,应使用有意义的标识
... /* program code */}
enum trunk_state_e
{TRUNK_IDLE = 0,TRUNK_BUSY = 1
};if (Trunk[index].trunk_state == TRUNK_IDLE)
{Trunk[index].trunk_state = TRUNK_BUSY;
... /* program code */}
3、不要使用难懂的技巧性很高的语句,除非证明改语句是性能瓶颈。
4、为了方便书写及记忆,变量类型采用如下重定义:
typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned long int uint32_t;typedef signed char int8_t;typedef signed short int16_t;typedef signed long int int32_t;#define __IO volatile
5、对于一些常见类型的变量,应在其名字前标注表示其类型的前缀。前缀用小写字母表示。前缀的使用请参照下列表格中说明。
6、变量作用域的前缀
为了清晰的标识变量的作用域,减少发生命名冲突,应该在变量类型前缀之前再加上表示变量作用域的前缀,并在变量类型前缀和变量作用域前缀之间用下划线‘-’隔开。
具体的规则如下:
(1)对于全局变量(global variable),在其名称前加“g”和变量类型符号前缀。
/** 全局变量 */
uint32_t g_ulParaWord;/** 全局变量 */
uint8_t g_ucByte;
(2)对于静态变量(static variable),在其名称前加“s”和变量类型符号前缀。
/** 静态变量 */
static uint32_t s_ulParaWord;/** 静态变量 */
static uint8_t s_ucByte;
(3)函数内部等局部变量前不加作用域前缀。
(4)对于常量,当可能发生作用域和名字冲突问题时,以上几条规则对于常量同样适用。注意,虽然常量名的核心部分全部大写,但此时常量的前缀仍然用小写字母,以保持前缀的一致性。
嵌入式C语言代码规范相关推荐
- C语言代码规范(编程规范)
首页 > 编程笔记 > C语言笔记 阅读:7,165 C语言代码规范(编程规范) C语言中文网推出辅导班啦,包括「C语言辅导班.C++辅导班.算法/数据结构辅导班」,全部都是一对一教学:一 ...
- 嵌入式C语言编程规范
前言 代码首先是给人看的,其次才是给机器执行的,因此一般情况下代码的可读性优先于性能,只有确定性能是瓶颈时,才需要主动优化. 可读性高的代码应当是易于理解并且易于实现的,代码越长越难看懂,可能出错的地 ...
- go语言代码规范详解
本规范旨在为日常Go项目开发提供一个代码的规范指导,方便团队形成一个统一的代码风格,提高代码的可读性,规范性和统一性.本规范将从命名规范,注释规范,代码风格和 Go 语言提供的常用的工具这几个方面做一 ...
- 嵌入式C语言编码规范参考
1 总则 1.1 目的 本规范主要目的是定义基于嵌入式C 编码的总体规范,确保编码的规范性,提高程序的可维护性.通过遵循共同的编码规范,程序开发人员可以保持代码一贯的风格,提高代码编写的可读性和使用的 ...
- 嵌入式C语言编程规范(个人规约)
0规范制定说明 0.1箴言 技术人员设计程序的首要目的是用于技术人员沟通和交流,其次才是用于机器执行.程序的生命力在于用户使用,程序的成长在于后期的维护及根据用户需求更新和升级功能.如果你的程序只能由 ...
- C语言代码规范(九)运算符优先级使用括号提高阅读性
举简单例子 a = b | c << d + 2; 对于大牛没有问题,对于我这样的码农需要思考一下运算优先级 对于这种情况华某有规范使用括号来表示运算顺序,从而提高代码可阅读性 a = b ...
- C语言代码规范(四)命名规则
一.宏定义全部字母大写,单词间下划线间隔 #define FLASH_PAGE_SIZE 256 #define FLASH_SECTOR_SIZE (4 * 1024) #define FLASH_ ...
- C语言代码规范(一)缩进与换行
一.缩进的空格数为4个.最好配置代码编辑器将TAB键设置为空格替换,避免出现另一个编辑器打开时格式变乱的情况. 例如Notepad++设置 KEIL设置 二."{" 和 " ...
- 2011软考软件设计师:C语言代码规范问题(1
1. C言语书写规范 1. 1符号命名规则 1. 1. 1符号名包括模块名.常量名.标号名.子顺序名等. 这些名字应该能反映它所代表的实践东西, 具有一定的意义, 用大写字母命名. 除了规则以外, ( ...
最新文章
- LeetCode简单题之数组形式的整数加法
- 【SQL】sql语句GROUP BY
- PingCode 全年上线功能盘点
- Android应用程序键盘(Keyboard)消息处理机制分析(8)
- 使用代理网络配置maven,显示导入失败的原因
- python舵机控制程序_树莓派PWM控制舵机的两种方式
- C# 网络编程之豆瓣OAuth2.0认证详解和遇到的各种问题及解决
- 成都2021高考二诊成绩查询,成都市2020高三二诊成绩查询
- 华为笔记本Win11更新时由于驱动问题引起蓝牙鼠标经常断开问题解决方法
- [EDA] 第1章 EDA技术概述-潘松版
- 实现Modbus ASCII多主站应用
- 2.WindowsServer2012R2装完的一些友好化设置
- sublime 3 3083验证码
- 【剑指Offer】60、把二叉树打印成多行
- 江苏计算机类事业编总分多少,必看!江苏事业单位统考三类岗位分值分布
- C++入门教程(23)深度优先,广度优先(连连看判断是否可以消除)
- tc275怎么移植到ram中去,把函数
- 2021年电子元器件行业涨价趋势已现
- 冒泡法排序(从小到大)
- Web前端工程师知识体系大全,Web前端入门基础体系