一、背景与目标
- 背景
- 代码规范的重要性
- 代码能力
- 目标
- 提升代码一致性
- 提升代码可读性
- 代码高内聚、低耦合
二、规范概览
1. 命名规则
-
文件命名规则(小写字母)
业务相关文件:yj_ble_event.c
解释:yj 公司名称缩写
ble 所属模块
event 功能内容
业务无关:http_server_logs.h -
函数命名规则
- 函数名称可采用驼峰命名法
- 首字母小写
- 若命名过长可在字段中间加 _
ble_otaStartHandle()
setMotorSpeed()
initHardware()
publishLightValue() -
变量命名规则
- 全部小写,使用 _进行连接
- 除非逻辑上需要,避免命名中出现数字编号。
普通变量:
int num_errors;
int_num_conpleted_connections;
不要使用缩写
int error_count; //Good
int error_cnt; //Bad
全局变量:
少用;加 g_
常量:
const int kDaysInAWeek = 7;
- 指针
- 加前缀p/p_单词。全小写 - 宏定义
- 全部大写,长字段使用_进行分割
R_SPEED
WIFI_SSID
SYSTEM_VERSION
CHINA_FOOTBALL - 结构体
- 单词首字母全大写,以_ST/_T结尾
typedef struct{
char *name;
uint8_t name_len;
uint8_t age;
}Students_T - 枚举
- 单词首字母全大写,类型定义尾缀加_E
2. 编码方式
不同的编码方式会导致在工程合并时出现乱码的现象,限定公司的文件编码统一为UTF-8
3. 头文件
每个头文件的框架采用如下格式(举例的头文件名字为ESPJarvis.h)
#ifndef _ESPJARVIS_H
#define _ESPJARVIS_H
#ifdef __cplusplus
extern "C" {
#endif
头文件内容
#ifdef __cplusplus
}#endif
#endif // _ESPJARVIS_H
使用 #ifdef __cplusplus 可以增加对C++项目引用的支持,当在一个C++项目引用这个头文件时,编译器能知道要按照C语言对此文件进行编译。
小贴士
使用 VSCode 开发的童鞋可以使用用户代码片段这个功能,新建的全局代码片段可以命名为snippet,每次创建新的头文件之后只需要输入def,IDE就能够自动提示选择插入相应的代码
{
"#ifndef … #define … #endif":{
"prefix": "def",
"body": "#ifndef ${1:${TM_FILENAME_BASE/(.*)/_${1:/upcase}_H/i}} \n#define $1 \n#ifdef __cplusplus\nextern \"C\" {\n#endif\n${2:}\n\n\n#ifdef __cplusplus\n}\n#endif\n#endif\t// $1"
}
全局代码片段功能 自动生成的代码效果如下 (创建的文件名称为test.h)
#ifndef _TEST_H
#define _TEST_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif // _TEST_H
以下是一些要点
- 头文件中放置接口的声明,不能放置实现
每个.c文件应有一个同名.h文件,用于声明需对外公开的接口。
只能通过包含.h文件的方式使用其他.c文件提供的接口,禁止在.c中extern使用外部接口。 - 头文件应尽可能少包含/依赖其他头文件
接口声明与包含头文件过于复杂会导致编译时间过长。
.c/.h文件禁止包含用不到的头文件。
4. 函数
- 一个功能函数仅实现一种功能
- 一个功能函数尽可能具有通用性,不依赖函数输入外的变量。
- 一般一个功能函数不能超过80-100行代码,如果过长要考虑功能拆分。
- 一个函数尽可能不要依赖另一个函数去完成功能。
- 一个函数内代码块嵌套不超过4层
- 冗余代码考虑提炼成函数(若一个处理流程重复了3次以上)
- 编写函数时,逻辑与数据要分开。
- 没有被调用的变量与函数要及时清除。
- 可重入函数不可使用共享变量
- 若必须使用共享变量,应利用互斥手段(信号量、中断)进行保护。
- 内部函数应该增加 static 关键字
- 声明源文件内可用,避免与其他文件或库中的相同标识符发生混淆。
- 函数内谨慎使用全局变量、静态局部变量和IO操作
- 使用时需考虑函数可重入、函数功能可预测,以及IO操作混乱。
- 检查参数合法性由调用者还是接口函数完成,项目组应统一规定
- 避免两者都进行参数的合法性检查,产生冗余代码。
- 接口函数内应对全局变量、数据文件等非参数输入进行有效性的检查。
三、补充描述
质量保证
- 代码要具有正确性、简洁性、可维护、可测试、高性能、可移植性
- 操作符优先级不确定加括号
- 避免内存操作越界、内存泄露
注意数组分配内存、数组下标、指针加减操作、字符串操作等。
函数异常出口出要判断资源是否全部释放。
禁止使用已经被释放的内存。
代码编辑、编译 - 理解所有警告,修改代码消除所有警告
降低警告级别从而消除警告是不可取的。
要统一编译开关、静态检查选项和告警清除策略。 - 本地构建工具的配置与持续集成的一致
通过本地构建的代码要及时签入版本控制系统。
如有纰漏、还请多多包涵、欢迎指正并补充