修复规范矛盾并定案5项规则,保护宏统一XXX_H

规则定案:常量在右(a>5)、保护宏XXX_H(禁双下划线)、
头文件常量用#define、存储类前缀(g_/s_)优先、允许void返回值
全库32个.h头文件保护宏 __XXX_H → XXX_H 改名(字节级替换)
S1检查规则同步更新(拒绝双下划线),Inc/gpio.h 反向验证被正确拦截
规范示例矛盾修复:K&R括号、标准类型、变量初始化、命名常量、注释字段补全
This commit is contained in:
2026-09-01 16:07:00 +08:00
parent 2b66f96d01
commit bb76cfd779
35 changed files with 158 additions and 138 deletions
+1 -1
View File
@@ -126,7 +126,7 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
| 编号 | 规范条款 | 规则 |
|---|---|---|
| S1 | 2.3.1 | .h 文件必须有 `__XXX_H` 格式头文件保护宏 |
| S1 | 2.3.1 | .h 文件必须有 `XXX_H` 格式头文件保护宏(禁止 `__` 前缀) |
| S2 | 5.2 | 文件开头必须有文件头注释(含 模块名称/作者) |
| S3 | 3.4.1 | `#define` 宏名必须全大写+下划线+数字 |
| S4 | 3.5.1 | typedef 类型名必须以 `_t` 结尾 |
@@ -8,12 +8,13 @@
| 版本号 | 修订日期 | 修订内容 | 修订人 |
| ---- | ---------- | ------ | --- |
| V1.0 | 2026-05-11 | 创建初始版本 | 王建锋 |
| V1.0.1 | 2026-09-01 | 修复示例与规则矛盾(括号风格、示例类型、变量初始化、硬编码、注释补全);规则定案:保护宏改`XXX_H`、常量在右、头文件常量用`#define`、存储类前缀优先、允许`void`返回值 | 王建锋 |
## 2. 文件结构规范
### 2.1 头文件(.h)结构
```c
#ifndef __MODULE_NAME_H
#define __MODULE_NAME_H
#ifndef MODULE_NAME_H
#define MODULE_NAME_H
/*
* 模块名称:模块英文名称
@@ -30,7 +31,7 @@ extern "C" {
#endif
/* 头文件包含区 - 仅包含本模块必需的头文件 */
#include "stdint.h"
#include <stdint.h>
/* 宏定义区 */
#define MODULE_NAME_CONSTANT 100
@@ -48,7 +49,7 @@ void module_name_init(void);
}
#endif
#endif /* __MODULE_NAME_H */
#endif /* MODULE_NAME_H */
```
### 2.2 源文件(.c)结构
```c
@@ -74,10 +75,10 @@ typedef struct {
} module_name_private_t;
/* 全局变量定义区 - 尽量避免使用全局变量 */
uint8_t g_module_name_global_var = 0;
uint8_t g_module_name_global_var = 0; /* 全局状态变量(示例) */
/* 静态变量定义区 */
static module_name_private_t s_module_name_private_var;
static module_name_private_t s_module_name_private_var; /* 私有状态变量(示例) */
/* 私有函数声明区 */
static void module_name_private_function(void);
@@ -92,7 +93,7 @@ static void module_name_private_function(void) {
}
```
### 2.3 头文件包含规则
1. 头文件必须包含头文件保护宏,格式为`__MODULE_NAME_H`
1. 头文件必须包含头文件保护宏,格式为`MODULE_NAME_H`(不得使用`__`双下划线前缀,其为C标准保留标识符)
2. 头文件中只包含本模块接口必需的其他头文件
3. 源文件中先包含系统头文件,再包含自定义头文件
4. 禁止在头文件中定义变量和函数体
@@ -111,13 +112,14 @@ static void module_name_private_function(void) {
4. 指针变量以`p_`前缀开头
5. 数组变量以`a_`前缀开头
6. 布尔变量以`is_`、`has_`、`can_`等前缀开头
7. 前缀冲突时,存储类前缀(`g_`/`s_`)优先于类型前缀(`p_`/`a_`),如静态数组`s_uart_rx_buffer`
**示例:**
```c
uint8_t g_system_status; /* 全局系统状态变量 */
static uint16_t s_timer_count; /* 静态定时器计数变量 */
uint8_t *p_data_buffer; /* 数据缓冲区指针 */
uint16_t a_adc_value[10]; /* ADC采样值数组 */
bool is_button_pressed; /* 按钮是否按下标志 */
uint8_t g_system_status = 0; /* 全局系统状态变量 */
static uint16_t s_timer_count = 0; /* 静态定时器计数变量 */
uint8_t *p_data_buffer = NULL; /* 数据缓冲区指针 */
uint16_t a_adc_value[10] = { 0 }; /* ADC采样值数组 */
bool is_button_pressed = false; /* 按钮是否按下标志 */
```
### 3.3 函数命名
1. 采用**小写字母+下划线**命名法
@@ -136,13 +138,15 @@ static void uart_private_handle_interrupt(void);
### 3.4 宏和常量命名
1. 采用**大写字母+下划线**命名法
2. 以**模块名**作为前缀
3. 常量优先使用`const`定义,而非`#define`
3. 头文件对外常量使用`#define`(见2.3.4);源文件内私有常量可用`const`,命名遵循3.2(小写+下划线)
**示例:**
```c
/* 头文件对外常量:使用 #define */
#define UART_BAUD_RATE_9600 9600
#define UART_BUFFER_SIZE 128
const uint8_t UART_DEFAULT_DATA_BITS = 8;
/* 源文件内私有常量:可用 const,命名遵循 3.2(小写) */
const uint8_t uart_default_data_bits = 8;
```
### 3.5 类型定义命名
1. 采用**小写字母+下划线**命名法
@@ -176,7 +180,11 @@ typedef struct {
5. 一元运算符前后不加空格
**正确示例:**
```c
int a = 10;
int32_t a = 10;
int32_t b = 0;
int32_t i = 0;
uint8_t c[10] = { 0 };
if (a > 5) {
b = a + 3;
}
@@ -186,7 +194,10 @@ for (i = 0; i < 10; i++) {
```
**错误示例:**
```c
int a=10;
int32_t a=10;
int32_t b=0;
int32_t i=0;
uint8_t c[10]={0};
if(a>5){
b=a+3;
}
@@ -202,8 +213,8 @@ for(i=0;i<10;i++){
5. 长表达式应在运算符处换行,新行与运算符对齐
**示例:**
```c
int calculate_sum(int a, int b, int c, int d) {
int sum;
int32_t calculate_sum(int32_t a, int32_t b, int32_t c, int32_t d) {
int32_t sum = 0;
sum = a + b
+ c
@@ -260,21 +271,25 @@ while (1) ;
```
**示例:**
```c
#define DELAY_INNER_LOOP 123 /* 延时内层循环次数,按12MHz时钟整定 */
/*
* 函数功能:毫秒级软件延时函数
* 入口参数:ms - 需要延时的毫秒数 unsigned int 0 - 65535
* 入口参数:ms - 需要延时的毫秒数 uint32_t 0 - 65535
* 出口参数:无
* 返回值:无(void)
* 限定条件:0 <= ms <= 65535
* 函数说明:1. 采用空指令循环方式实现延时,会阻塞CPU运行
* 2. 延时精度依赖系统时钟,默认适配12MHz时钟(12T模式)
* 3. 系统时钟改变时,需重新调整内层循环次数
* 2. 延时精度依赖系统时钟,默认适配12MHz时钟
* 3. 系统时钟改变时,需重新调整内层循环次数(DELAY_INNER_LOOP)
* 4. 当ms为0时,函数立即返回
*/
void delay_ms(unsigned int ms) {
unsigned int i;
unsigned int j;
void delay_ms(uint32_t ms) {
uint32_t i;
uint32_t j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 123; j++) {
for (j = 0; j < DELAY_INNER_LOOP; j++) {
}
}
}
@@ -293,13 +308,16 @@ static uint8_t s_uart_rx_buffer[UART_BUFFER_SIZE]; /* UART接收缓冲区 */
### 5.5 代码行注释
1. **关键逻辑代码每一行都要添加注释**
2. 复杂的算法和逻辑必须添加详细注释
3. 注释应单独占一行,与被注释代码缩进级别相同
3. 注释应单独占一行(变量定义的行内注释除外,见5.4.3),与被注释代码缩进级别相同
**示例:**
```c
#define CRC16_INITIAL 0xFFFF /* CRC-16初值 */
#define CRC16_POLY_REFLECTED 0xA001 /* CRC-16/MCC反射多项式 */
#define BITS_PER_BYTE 8 /* 每字节的位数 */
/* 计算CRC校验值 */
uint16_t crc_calculate(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
uint16_t crc_calculate(uint8_t *data, uint16_t length) {
uint16_t crc = CRC16_INITIAL;
uint16_t i;
uint16_t j;
@@ -309,11 +327,11 @@ uint16_t crc_calculate(uint8_t *data, uint16_t length)
crc ^= data[i];
/* 对每个位进行处理 */
for (j = 0; j < 8; j++) {
for (j = 0; j < BITS_PER_BYTE; j++) {
/* 检查最低位是否为1 */
if (crc & 0x0001) {
/* 最低位为1,右移并与多项式异或 */
crc = (crc >> 1) ^ 0xA001;
crc = (crc >> 1) ^ CRC16_POLY_REFLECTED;
} else {
/* 最低位为0,直接右移 */
crc = crc >> 1;
@@ -334,12 +352,14 @@ uint16_t crc_calculate(uint8_t *data, uint16_t length)
5. 使用标准数据类型(`uint8_t`、`int32_t`等),避免使用`char`、`int`等不确定长度的类型
**示例:**
```c
#define DATA_BUF_SIZE 100 /* 数据缓冲区大小(字节) */
void function(void) {
uint8_t status = 0;
uint16_t count = 0;
uint8_t *p_data = NULL;
p_data = (uint8_t *)malloc(100);
p_data = (uint8_t *)malloc(DATA_BUF_SIZE);
if (p_data == NULL) {
return;
}
@@ -354,17 +374,17 @@ void function(void) {
1. 函数应遵循"单一职责原则",一个函数只做一件事
2. 函数长度不宜过长,一般不超过50行
3. 函数参数不宜过多,一般不超过5个
4. 函数必须有明确的返回值,用于表示执行状态
4. 有失败路径的函数必须有明确的返回值,用于表示执行状态;无失败路径的纯输出函数可返回`void`
5. 避免使用函数参数作为返回值
6. 私有函数必须声明为`static`
### 6.3 控制结构
1. `if`语句中,常量应写在比较运算符的左边
1. `if`语句中,常量应写在比较运算符的右边
2. `switch`语句必须包含`default`分支
3. 避免使用`goto`语句,除非用于错误处理
4. 循环嵌套不宜超过3层
**示例:**
```c
if (0 == status) {
if (status == 0) {
do_something();
}
@@ -423,8 +443,8 @@ uint8_t uart_send_data(uint8_t *data, uint16_t length) {
## 9. 附录
### 9.1 完整示例代码
```c
#ifndef __LED_H
#define __LED_H
#ifndef LED_H
#define LED_H
/*
* 模块名称:LED控制模块
@@ -440,7 +460,7 @@ uint8_t uart_send_data(uint8_t *data, uint16_t length) {
extern "C" {
#endif
#include "stdint.h"
#include <stdint.h>
/* LED编号定义 */
#define LED_NUM_1 0
@@ -491,5 +511,5 @@ uint8_t led_toggle(uint8_t led_num);
}
#endif
#endif /* __LED_H */
#endif /* LED_H */
```