开发编码规范笔记
前言
(1)该博客仅用于个人笔记
格式转换
(1)查看是
LF
行尾还是CRLF
行尾。
# 单个文件,\n 表示 LF 行尾。\r\n 表示 CRLF 行尾。
hexdump -c <yourfile>
# 单个文件,'$' 表示 LF 行尾。'^M$' 表示 CRLF 行尾。
cat -e <yourfile>
(2)将文件转换为
LF
格式。
# 单个文件
dos2unix <yourfile>
# 批量操作
find <path> -type f -exec dos2unix {} \;
(3)将文件转换为
CRLF
格式。
# 单个文件
unix2dos <yourfile>
# 批量操作
find <path> -type f -exec unix2dos {} \;
C代码规范
断言
适用场景
(1)
assert()
只能用于检测由于严重的内部逻辑错误或损坏而导致程序无法继续运行的不可恢复的错误。对于可恢复的错误,包括由于无效的外部输入而可能出现的错对于误,应返回错误值。
(2)对于返回值为esp_err_t
类型的函数,应该使用ESP_ERROR_CHECK()
而不是assert()
。
断言设置使能
(1)对于断言的设置,可以进入
menuconfig
搜索CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL
进行配置:
- Enabled : 启动断言功能。当断言失败时,会打印出断言的内容和行号。适用于开发阶段,因为它可以帮助开发者快速定位和修复代码中的错误。
- Silent : 启动静默。断言失败时,不会打印出具体的断言信息和行号,而是直接中止程序。开发者需要通过中止地址来查找断言失败的位置。适用于在某些情况下需要节省代码大小的场景,同时仍然希望保留某种程度的断言检查。
- Disabled : 禁用断言。禁用断言后,任何断言检查都不会执行,从而提高程序的性能。
“变量设置但未使用”警告
(1)如果断言被失能,那么下面的
res
可能会出现“变量设置但未使用”警告。
int res = do_something();
assert(res == 0);
(2)为了避免这样的问题,我们可以让所有的返回值用同一个变量定义,然后加上关键字即可。
int res __attribute__((unused));res = do_something();
assert(res == 0);res = do_something_else();
assert(res != 0);
变量
前缀
(1)静态全局变量用
g_
前缀,静态局部变量用s_
前缀。作用域仅限于当前文件的变量必须声明为静态变量static
。
static uint8_t g_num; // 静态全局变量用 g_ 前缀
int main()
{static uint8_t s_num; // 静态局部变量用 s_ 前缀while (1);
}
使用
(2)变量注意重入问题。 尽量在一个固定函数中操作静态全局变量。使用
get_
set_
等接口进行变量操作。
static SemaphoreHandle_t g_mutexhandle = NULL; // 变量定义要赋初值,全局静态变量以 g_ 前缀
static uint8_t g_num = 0; // 变量定义要赋初值,全局静态变量以 g_ 前缀static void set_num(uint8_t value) // 使用 set_ 前缀接口操作变量
{// 获得信号量xSemaphoreTake(g_mutexhandle, portMAX_DELAY);g_num = value;// 释放信号量pthread_mutex_unlock(g_mutexhandle);
}static int get_num() // 使用 get_ 前缀接口操作变量
{uint8_t value;// 获得信号量xSemaphoreTake(g_mutexhandle, portMAX_DELAY);value = g_num;// 释放信号量pthread_mutex_unlock(g_mutexhandle);return value;
}int main()
{static uint8_t s_count; // 静态局部变量用 s_ 前缀// 创造互斥量g_mutexhandle = xSemaphoreCreateMutex();while(1){set_num(10);s_count = get_num(); // 静态全局变量用 g_ 前缀vTaskDelay(pdMS_TO_TICKS(1000));}vSemaphoreDelete(g_mutexhandle);g_mutexhandle = NULL; // 句柄类型变量,在对象销毁后,应重新赋值为 NULL
}
变量名
(1)变量应尽量使用有意义的词语,或者已经达成共识的符号或变量缩写
函数
(1)如果一个函数存在重入和线程安全问题,需在注释中说明。
/*** @brief 打印函数,该函数存在线程安全问题* * @param __restrict 字符串* @param ... 可变参数* @return int */
int printf (const char *__restrict, ...);
(2)函数名统一使用小写,同一组件保持同一前缀。
头文件
固定格式
(1)头文件固定如下格式。
#ifndef FILE_NAME_H /* 名字要与 .c 文件对应 */
#define FILE_NAME_H#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus *//********************************************* 头文件内容写里面********************************************/#ifdef __cplusplus
}
#endif /* __cplusplus */#endif /* FILE_NAME_H */
类型定义
(1)类型都需要通过
typedef
定义并且命名
typedef enum{MODULE_FOO_ONE,MODULE_FOO_TWO,MODULE_FOO_THREE
} module_foo_t; /* typedef 之后名字后缀为 _t */typedef struct {esp_chip_model_t model; uint32_t features; uint16_t revision; uint8_t cores;
} esp_chip_info_t; /* typedef 之后名字后缀为 _t */
格式化代码
(1)如果重头写一个文件,可以使用
astyle
工具。
# 格式化代码
astyle example.c
# 使用乐鑫官方脚本
${esp-idf}/tools/format.sh <yourfile>
最终代码演示
C代码
/********************************************************************************** 版权声明*********************************************************************************/
/** SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD** SPDX-License-Identifier: Apache-2.0*//********************************************************************************** 头文件规范*********************************************************************************/
// #include < C 标准库头文件 >
// #include < POSIX 头文件及其常见扩展 >
// #include " IDF 头文件 "
// #include " 组件头文件,例如 FreeRTOS "
// #include " 私有头文件 "#define uint8_t unsigned char
#define NULL 0
#define portMAX_DELAY -1/********************************************************************************** 变量定义规范*********************************************************************************/
static uint8_t g_num = 5, g_x = 0, g_y = 0; /* ","仅后面有空格,静态全局变量用 g_ 前缀 */
static uint8_t *g_z = NULL;
static SemaphoreHandle_t g_mutexhandle = NULL; // 互斥量/********************************************************************************** 代码规范*********************************************************************************/
static void circulate_function()
{/* 函数定义的括号应该单独一行 */if (g_num) { /* 循环关键字后面加一个空格,函数内左括号与条件放在同一行 */printf("hello");}else if (g_x) {printf("world");}for (; g_x < g_num; g_x++) { /* 循环关键字后面加一个空格,函数内左括号与循环放在同一行 */printf("esp");}while (g_x){ /* 循环关键字后面加一个空格,函数内左括号与循环放在同一行 */printf("esp32");}switch (g_num) { /* 循环关键字后面加一个空格,函数内左括号与循环放在同一行 */ case 0:break;default:break;}
}/* 尽量在一个固定函数中操作静态全局变量 */
static void set_num(uint8_t value) // 使用 set_ 前缀接口操作变量
{// 获得信号量xSemaphoreTake(g_mutexhandle, portMAX_DELAY);g_num = value;// 释放信号量pthread_mutex_unlock(g_mutexhandle);
}static int get_num() // 使用 get_ 前缀接口操作变量
{uint8_t value;// 获得信号量xSemaphoreTake(g_mutexhandle, portMAX_DELAY);value = g_num;// 释放信号量pthread_mutex_unlock(g_mutexhandle);return value;
}int main() /* 函数之间放置一个空行 */
{/* Tab 键为4个空格,而不是制表符进行缩进 *//* 如果不需要这行代码,直接删除,否则就解释禁用原因。 */// printf("hello world");static uint8_t s_count; // 静态局部变量用 s_ 前缀// 创造互斥量g_mutexhandle = xSemaphoreCreateMutex();while(1){set_num(10);s_count = get_num(); // 因为该变量不存在重入问题,因此不需要进行保护vTaskDelay(pdMS_TO_TICKS(1000));}vSemaphoreDelete(g_mutexhandle);g_mutexhandle = NULL; // 句柄类型变量,在对象销毁后,应重新赋值为 NULL// 获得信号量xSemaphoreTake(g_mutexhandle, portMAX_DELAY);/* 一元运算符不需要空格 */g_x = g_num++; g_y = g_num--; *g_z = &g_num; g_x = !g_num; g_x = ~g_x;g_y = *g_z;g_x = (uint8_t)g_x;/* 二元运算符需要空格 */g_num = g_x + g_y;g_num = g_x - g_y;g_num = g_x * g_y; /* 这个可以删除空格 */g_num = g_x*g_y; g_num = g_x / g_y; /* 这个可以删除空格 */g_num = g_x/g_y;g_num = g_x % g_y;g_num = (g_x == g_y);g_num = (g_x != g_y); g_num = (g_x > g_y); g_num = (g_x < g_y); g_num = (g_x >= g_y); g_num = (g_x <= g_y); g_num = (g_x && g_y); g_num = (g_x || g_y); g_num = g_x & g_y; g_num = g_x | g_y; g_num = g_x ^ g_y; g_num = g_x << 1; g_num = g_x >> 1; g_x += 3; g_x -= 2; g_x *= 2; g_x /= 4; g_x %= 2; g_y &= 3; g_y |= 2; g_y ^= 3; g_y <<= 1; g_y >>= 1; // 释放信号量pthread_mutex_unlock(g_mutexhandle);
}
头文件
#ifndef FILE_NAME_H /* 名字要与 .c 文件对应 */
#define FILE_NAME_H#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus *//* 枚举要通过 typedef 定义并且命名 */
typedef enum {MODULE_FOO_ONE,MODULE_FOO_TWO,MODULE_FOO_THREE
} module_foo_t; /* typedef 之后名字后缀为 _t *//*** @brief 该函数存在线程安全问题* * @param __restrict * @param ... * @return int */
int printf (const char *__restrict, ...);#ifdef __cplusplus
}
#endif /* __cplusplus */#endif /* FILE_NAME_H */
参考
(1)Espressif IoT Development Framework Style Guide
相关文章:

开发编码规范笔记
前言 (1)该博客仅用于个人笔记 格式转换 (1)查看是 LF 行尾还是CRLF 行尾。 # 单个文件,\n 表示 LF 行尾。\r\n 表示 CRLF 行尾。 hexdump -c <yourfile> # 单个文件,$ 表示 LF 行尾。^M$ 表示 CRLF …...

spring boot easyexcel
1.pom <!-- easyexcel 依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.projectlombok</group…...

Docker 部署 ShardingSphere-Proxy 数据库中间件
文章目录 Github官网文档ShardingSphere-Proxymysql-connector-java 驱动下载conf 配置global.yamldatabase-sharding.yamldatabase-readwrite-splitting.yamldockerdocker-compose.yml Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为…...

Qt常用快捷键
Qt中的常用快捷键 F1查看帮助F2快速到变量声明 从cpp→hShift F2 函数的声明和定义之间快速切换 ;选中函数名 ,从h→cppF4在 cpp 和 h 文件切换 Shift F4在cpp/h文件与 界面文件中切换Ctrl /注释当前行 或者选中的区域Ctrl I自动缩进当前…...

关于RiboSeq分析流程的总结
最近关注了一下RiboSeq的分析方法,方法挺多的,但是无论哪种软件,都会存在或多或少的问题,一点问题不存在的软件不存在,问题的原因出在,1.有的脚本是用python2编写的,目前python2已经不能用了 2.…...

NLP任务:情感分析、看图说话
我可不向其他博主那样拖泥带水,我有代码就直接贴在文章里,或者放到gitee供你们参考下载,虽然写的不咋滴,废话少说,上代码。 gitee码云地址: 卢东艺/pytorch_cv_nlp - 码云 - 开源中国 (gitee.com)https:/…...

Linux桌面溯源
X窗口系统(X Window System) Linux起源于X窗口系统(X Window System),亦即常说的X11,因其版本止于11之故。 X窗口系统(X Window System,也常称为X11或X)是一种以位图方式显示的软件窗口系统。…...

深入Linux:权限管理与常用命令详解
文章目录 ❤️Linux常用指令🩷zip/unzip指令🩷tar指令🩷bc指令🩷uname指令🩷shutdown指令 ❤️shell命令以及原理❤️什么是 Shell 命令❤️Linux权限管理的概念❤️Linux权限管理🩷文件访问者的分类&#…...

Mojo 编程语言:AI开发者的新宠儿
Mojo(Meta Object Oriented programming for Java Objects)是一种面向对象的编程语言,旨在简化和加速Java应用程序的开发过程。作为近年来新兴的编程语言,Mojo因其与Java的紧密集成以及AI开发领域的应用潜力而逐渐成为AI开发者的新…...

ARM/Linux嵌入式面经(十):极氪
开篇强调两个事情: pdf文件都在百度网盘群:911289806一定要把超链接里面的文章看了,那都是为了你们写的。老板!!!现在多学点,涨个2k工资,真的很值得。要不吃学习的苦,要不吃生活的苦。 1. 自我介绍 专开新篇,等我! 2. 项目介绍,提问 专开新篇,等我! 3. SPI通信和…...

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程
【PVE】新增2.5G网卡作为主网卡暨iperf测速流程 新增网卡 新增网卡的首先当然需要关闭PVE母机,把新网卡插上,我用淘宝遥现金搞了个红包,花了26元买了块SSU的2.5G网卡。说实话这个价位连散热片都没有,确实挺丐的。稍后测下速度看…...

数学建模美赛入门
数学建模需要的学科知识 高等数学线性代数 有很多算法的掌握是需要高等数学和线代的相关知识 如:灰色预测模型需要微积分知识;神经网络需要用到导数知识;图论和层次分析法等都需要用到矩阵计算的相关知识等; 概率论与数理统计&am…...

两段序列帧动画播放,在ios机型上出现闪屏
使用场景:两段序列帧动画连接播放,先播放第一段播一次,再播放第二段,第二段循环播放,在ios机型上出现动画闪动,播放不正常。 错误的写法:把每一段序列帧动画单独写在了定义的动画里 .gacha-bg…...

【C++深度探索】全面解析多态性机制(二)
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:C从入门至进阶 这里将会不定期更新有关C/C的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 前言 我…...

MySQL配置数据库的连接命令
MySQL配置数据库连接命令 在MySQL中,配置数据库连接的命令涉及创建用户、授予权限、配置主从复制等多个方面。以下是常用的命令及其用途: 创建用户 创建一个新的数据库用户并为其设置密码: CREATE USER usernamehost IDENTIFIED BY passwo…...

[PaddlePaddle飞桨] PaddleSpeech-自动语音识别-小模型部署
PaddleSpeech的GitHub项目地址 环境要求: gcc > 4.8.5 paddlepaddle < 2.5.1 python > 3.8 OS support: Linux(recommend), Windows, Mac OSXpip下载指令: python -m pip install paddlepaddle-gpu2.5.1 -i https://pypi.tuna.tsinghua.edu.c…...

redis查询慢,你们是如何排查优化的?(总结篇)
1,先进行基准测试,查看redis是否存在查询过慢情况,根据自己的情况而定 2、检查网络连接是否出现延迟,数据丢包问题(可能性小 3、开启慢查询日志,通过日志可以清楚知道哪些命令比较耗时,同时避…...

Docker 容器出现 IP 冲突
Docker 容器出现 IP 冲突的情况可能由以下几个原因导致: 静态 IP 分配:如果你在 docker-compose.yml 文件中为多个容器手动设置了相同的静态 IP 地址,那么这些容器在启动时就会出现 IP 冲突。确保每个容器分配的静态 IP 地址是唯一的。桥接网…...

paddlepaddle2.6,paddleorc2.8,cuda12,cudnn,nccl,python10环境
1.安装英伟达显卡驱动 首先需要到NAVIDIA官网去查自己的电脑是不是支持GPU运算。 网址是:CUDA GPUs | NVIDIA Developer。打开后的界面大致如下,只要里边有对应的型号就可以用GPU运算,并且每一款设备都列出来相关的计算能力(Compu…...

【D3.js in Action 3 精译】1.3 D3 视角下的数据可视化最佳实践(上)
当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介 1.1 何为 D3.js?1.2 D3 生态系统——入门须知 1.2.1 HTML 与 DOM1.2.2 SVG - 可缩放矢量图形1.2.3 Canvas 与 WebGL1.2.4 CSS1.2.5 JavaScript1.2.6 Node 与 JavaScript 框架1.2.7 Observable 记事本 1…...

如何在Linux上如何配置虚拟主机
在Linux上配置虚拟主机可以通过使用Apache HTTP服务器来实现。Apache是一个开源的跨平台的Web服务器软件,可以在多种操作系统上运行并支持虚拟主机的配置。 以下是在Linux上配置虚拟主机的步骤: 安装Apache HTTP服务器 在终端中运行以下命令来安装Apache…...

c语言alpha-beta剪枝六子棋
c语言Alpha-Beta剪枝算法六子棋[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2i5w8kc1-1720756528545)(https://i-blog.csdnimg.cn/direct/464b9db7d6384a63ab8c3213efff0e99.png)] 1.介绍 Alpha-Beta剪枝算法是一种用于优化博弈树搜索的算法&…...

基于PyTorch深度学习实践技术应用
近年来,Python语言由于其开源、简单等特点,受到了广大程序开发者的偏爱,丰富的函数库使得其在各行各业中得到了广泛的应用。伴随着新一轮人工智能(尤其是深度学习)的快速发展,许多深度学习框架应运而生&…...

数据湖仓一体(五)安装spark
上传安装包到/opt/software目录并解压 [bigdatanode106 software]$ tar -zxvf spark-3.3.1-bin-hadoop3.tgz -C /opt/services/ 重命名文件 [bigdatanode106 services]$ mv spark-3.3.1-bin-hadoop3 spark-3.3.1 配置环境变量 [bigdatanode106 ~]$ sudo vim /etc/profile…...

项目收获总结--本地缓存方案选型及使用缓存的坑
本地缓存方案选型及使用缓存的坑 一、摘要二、本地缓存三、本地缓存实现方案3.1 自己编程实现一个缓存3.2 基于 Guava Cache 实现本地缓存3.3 基于 Caffeine 实现本地缓存3.4 基于 Encache 实现本地缓存3.5 小结 四、使用缓存的坑4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩4.4 数据…...

java使用poi-tl模版引擎导出word之if判断条件的使用
文章目录 模版中if语句条件的使用1.数据为False或空集合2.非False或非空集合 模版中if语句条件的使用 如果区块对的值是 null 、false 或者空的集合,位于区块中的所有文档元素将不会显示,这就等同于if语句的条件为 false。语法示例:{{?stat…...

扩散的魔法:如何打造未来生物打印?
生物打印技术正在快速发展,它允许我们将生物材料、细胞和生长因子等生物活性成分精确地打印成具有特定形状和功能的结构。而扩散现象在生物打印中扮演着至关重要的角色,它影响着打印结构的特性、机械性能、生物功能和形态。为了更好地利用扩散现象&#…...

Bag of mice(概率dp)
https://www.luogu.com.cn/problem/CF148D 思路: 概率dp,设f[a][b]为白鼠为a个,黑鼠为b个时,赢的期望。 f[i][0]1; 1.当先手取到白鼠时 a/(ab); 2.当先手未取到白鼠,先手要向赢,后手也不能取到白鼠&am…...

Python的基础语法——持续更新版
1、type查看数据类型 # 直接输出结果 print(type("Hello")) # 先用变量存储 string_type type("Hello") print(string_type) 2、 类型转化 任何类型可以转化为字符串,但字符串不可以随意转化,要求字符串类内容都是数字 # 类型…...

百度智能云将大模型引入网络故障定位的智能运维实践
物理网络中,某个设备发生故障,可能会引起一系列指标异常的告警。如何在短时间内从这些告警信息中找到真正的故障原因,犹如大海捞针,对于运维团队是一件很有挑战的事情。 在长期的物理网络运维工作建设中,百度智能云通…...