2. 命名规范(上)

命名这件事,说大不大,说小不小。我见过太多项目,代码逻辑写得挺好,一看命名——全是一堆 a、b、tmp、data1、data2……你想想看,三个月后你自己回来看,能记得 data1 是啥意思吗?

我个人习惯是:命名就是给代码写注释。好的命名,根本不需要额外注释。今天咱们就把变量、函数、宏、文件这四类命名规则捋清楚。

2.1 变量命名:见名知意,别偷懒

变量命名是基本功。我刚开始写代码时也图省事,用 i、j、k 满天飞。后来有一次调试一个电机控制程序,满屏的 cnt1、cnt2、cnt3,我盯着看了半小时才分清楚哪个是速度计数、哪个是位置计数。从那以后,我再也不敢乱起名了。

2.1.1 命名风格:小驼峰 + 下划线

嵌入式 C 语言里,我推荐小驼峰 + 下划线混合风格。具体来说:

  • 局部变量:小驼峰,比如 motorSpeed、adcValue
  • 全局变量:加前缀 g_,比如 g_systemTick、g_temperature
  • 静态变量:加前缀 s_,比如 s_lastError、s_bufferIndex

核心原则:变量名要能准确描述它的用途和数据类型。

举个例子:

// 不好的命名
int a;
int b;
int c;

// 好的命名
int motorSpeed;        // 电机转速
int adcRawValue;       // ADC 原始采样值
int errorCode;         // 错误码

2.1.2 常见变量类型命名模板

我整理了一个常用模板,你可以直接套用:

变量类型 命名模板 示例
计数器 xxxCount retryCount
标志位 xxxFlag timeoutFlag
索引 xxxIndex bufferIndex
状态 xxxStatus motorStatus
时间 xxxTimeMs delayTimeMs

小技巧:变量名里带上单位,比如 timeoutMs、speedRpm,能避免很多单位换算的 bug。我在项目中吃过这个亏,一个时间参数没写单位,结果有人传了秒、有人传了毫秒……

2.2 函数命名:动词开头,职责清晰

函数命名比变量命名更讲究。为什么?因为函数是代码的「动词」,它要做一件事,名字就得把这件事说清楚。

2.2.1 命名风格:动词 + 名词

我建议函数名采用动词 + 名词结构。动词表明操作,名词表明操作对象。

// 不好的命名
void process(void);
void handle(void);
void doSomething(void);

// 好的命名
void uartSendByte(uint8_t data);
int  i2cReadRegister(uint8_t regAddr);
void ledSetBrightness(uint8_t level);

2.2.2 常用动词前缀

这里我列几个常用的动词前缀,都是我在实际项目中反复用到的:

动词 含义 示例
get 获取值 getTemperature
set 设置值 setMotorSpeed
init 初始化 initUart
is 判断真假 isTimeout
enable 使能 enableInterrupt
disable 禁止 disableWatchdog

注意:函数名不要超过 30 个字符。太长的函数名说明这个函数可能做了太多事,该拆分了。我曾经接手过一个叫 processAndUpdateAndSendAndLog 的函数……嗯,你懂的。

2.3 宏命名:全大写 + 下划线,别犹豫

宏的命名规则最统一,也最简单——全大写 + 下划线。这一点几乎没什么争议。

2.3.1 常量宏

#define BUFFER_SIZE     256
#define TIMEOUT_MS      1000
#define MAX_RETRY_COUNT 3

2.3.2 函数式宏

函数式宏也遵循全大写规则,但要注意参数用括号包好,避免展开出问题。

#define MIN(a, b)       ((a) < (b) ? (a) : (b))
#define ABS(x)          ((x) > 0 ? (x) : -(x))
#define IS_BIT_SET(x, b) ((x) & (1UL << (b)))

避坑指南:宏名不要和变量名、函数名冲突。我曾经在一个项目里看到有人定义了 #define delay 100,结果代码里所有叫 delay 的变量都被替换成了 100……编译报错报了一整天。

2.4 文件命名:模块化 + 层次化

文件命名是很多人容易忽略的。其实文件命名直接决定了项目的可维护性。

2.4.1 命名规则:模块名_功能

我推荐用模块名_功能的格式。模块名小写,功能部分小写,用下划线分隔。

// 好的文件命名
uart_driver.c
uart_driver.h
motor_control.c
motor_control.h
sensor_temperature.c
sensor_temperature.h

// 不好的文件命名
my_code.c
test.c
utils.c
common.c

2.4.2 头文件与源文件对应

每个 .c 文件都应该有一个对应的 .h 文件,文件名相同。这是基本要求。

源文件 头文件 说明
uart_driver.c uart_driver.h UART 驱动模块
motor_control.c motor_control.h 电机控制模块
sensor_temperature.c sensor_temperature.h 温度传感器模块

个人经验:文件名不要超过 40 个字符。太长的文件名在 Git 里看着难受,在文件系统里也容易出问题。另外,文件名里不要用空格和中文,这个应该不用我多说了吧?

2.5 本章知识体系

下面这张图帮你梳理了本章的核心内容,建议保存下来当 cheat sheet 用。

命名规范知识体系 变量命名 函数命名 宏命名 文件命名 局部变量:小驼峰 全局变量:g_前缀 静态变量:s_前缀 动词 + 名词结构 常用前缀:get/set/init 不超过 30 字符 全大写 + 下划线 常量宏:BUFFER_SIZE 函数式宏:参数加括号 模块名_功能 .c 与 .h 对应 不超过 40 字符 核心原则:见名知意,风格统一 好的命名 = 自文档化的代码

好了,命名规范的上半部分就讲到这里。变量、函数、宏、文件这四类命名,说白了就是一句话:别让读你代码的人猜。你写的时候觉得理所当然,别人看的时候可能就是一头雾水。