C语言:配置参数的开发规范

核心原则

杜绝零散全局变量、杜绝魔数、按场景结构化收拢,易维护、易初始化、易传参、易兼容协议。

一、场景1:基础少量配置(5个以内,简单模块)

规范:常量 + 宏定义(只读固定配置)

适用:固件固定参数、波特率、超时阈值、引脚号

// config.h 统一归集,不散落代码里
#define UART_BAUD_RATE     115200U
#define MODULE_TIMEOUT_MS  500U
#define LED_GPIO_PIN       GPIO_PIN_5

规范约束:

  1. 全大写+下划线命名;
  2. 加类型后缀 U/L 防隐式转换;
  3. 全部放独立头文件,禁止散落在业务c文件。

二、场景2:可修改/运行时可调配置(最常用!重点)

规范:用 结构体聚合所有参数(企业强制规范)

优势:传参只传一个结构体指针、初始化集中、代码整洁、不易漏参数。

1. 定义配置结构体(按模块拆分,不全局一锅烩)

// app_config.h
typedef struct
{
    /* 通信配置 */
    uint32_t uart_baud;
    uint16_t mqtt_port;
    uint8_t  mqtt_client_id[32];

    /* 业务阈值 */
    uint16_t temp_high_limit;
    uint16_t humi_low_limit;

    /* 硬件控制 */
    uint8_t  pump_ctrl_enable;
    uint32_t sample_interval_ms;

} AppConfig_t;

2. 全局单实例 + 外部引用规范

// app_config.c
static AppConfig_t g_app_config;  // static 私有化,防越权修改

// 只读获取接口(规范:禁止直接外部修改全局结构体)
const AppConfig_t *AppConfig_GetReadOnly(void)
{
    return &g_app_config;
}

// 统一修改接口(校验+赋值,防非法参数)
int AppConfig_Update(const AppConfig_t *new_cfg)
{
    if(NULL == new_cfg) return -1;
    // 参数合法性校验(强规范必备)
    if(new_cfg->sample_interval_ms > 10000U) return -2;

    memcpy(&g_app_config, new_cfg, sizeof(AppConfig_t));
    return 0;
}

3. 默认初始化规范

void AppConfig_InitDefault(void)
{
    AppConfig_t def = {
        .uart_baud = 115200U,
        .mqtt_port = 1883U,
        .temp_high_limit = 600U,
        .sample_interval_ms = 1000U,
        .pump_ctrl_enable = 1U
    };
    memcpy(&g_app_config, &def, sizeof(def));
}

4. 业务层使用(干净极简)

void Sensor_Start(void)
{
    const AppConfig_t *cfg = AppConfig_GetReadOnly();
    HAL_UART_Init(cfg->uart_baud);
    MQTT_Connect(cfg->mqtt_port);
}

三、场景3:多组不同配置(出厂配置/用户配置/调试配置)

规范:多结构体实例 + 切换接口

static AppConfig_t g_factory_cfg;
static AppConfig_t g_user_cfg;

// 一键切换出厂默认
void AppConfig_RestoreFactory(void);

四、场景4:需要落盘保存(Flash/EEPROM)

规范:结构体 + 校验和CRC(工业防损坏规范)

typedef struct
{
    AppConfig_t cfg;
    uint32_t    crc32;   // 校验位,防止配置损坏
} SaveConfig_t;

读写时:校验CRC合法再加载,不合法自动恢复默认。


五、C语言编码硬性规范(团队必守)

  1. 禁止零散全局变量
    多个参数绝不单独定义 int a; int b;,必须结构体收拢。
  2. 私有全局static化
    配置实例加static隐藏,外部只能通过函数访问,禁止直接extern篡改。
  3. 参数必须合法性校验
    范围、边界、空指针全校验,避免非法配置死机。
  4. 统一初始化入口
    上电只调用一次Config_Init(),不零散初始化。
  5. 字符串/数组固定长度
    比如mqtt clientid[32],避免动态内存碎片,适配嵌入式。
  6. 搭配你之前学的snprintf
    拼接配置字符串时,用结构体字段统一取值,安全格式化。

六、极简选型口诀

  1. 固定不变 → 宏定义归集头文件
  2. 运行可改少量/大量 → 结构体+私有全局+读写接口
  3. 需要存储 → 结构体+CRC校验落盘
  4. 多套参数 → 多实例结构体切换

需要我结合你鸿蒙Hi3861 + MQTT项目,直接给你一套可照搬的完整配置结构体+初始化+读写模板吗?