3. 命名规范(下)
上一章我们聊了命名规范的基本原则。今天来点更实际的——三种主流命名法,到底怎么选?
说实话,这个问题我年轻时也纠结过。刚入行那会儿,看到前辈代码里既有iCount又有g_nTotal,还有user_name,整个人都是懵的。后来踩了不少坑,才慢慢摸出门道。
一、三种命名法,先认识一下
咱们先快速过一遍,这三种命名法长什么样。
| 命名法 | 示例 | 核心特点 |
|---|---|---|
| 匈牙利命名法 | iCount、szName、pBuffer |
变量名前缀表示类型 |
| 驼峰命名法 | userName、getTotalCount |
首单词小写,后续单词首字母大写 |
| 下划线命名法 | user_name、get_total_count |
单词间用下划线分隔 |
嗯,看起来都不复杂。但问题来了——我该用哪个?
二、匈牙利命名法:老古董还是真香?
匈牙利命名法,说白了就是在变量名前面加个类型前缀。i表示int,sz表示以零结尾的字符串,p表示指针。
我在项目中遇到过一位老工程师,他的代码全是匈牙利命名法。当时我接手他的模块,看到pData、iLen、hFile这些名字,第一反应是「这什么鬼?」。但读了两天代码后,我不得不承认——确实能一眼看出变量类型。
匈牙利命名法的优缺点
- 优点:类型信息一目了然,适合大型项目快速定位
- 缺点:现代IDE都能显示类型,前缀反而冗余;重构时改类型还得改名字,麻烦
注意:在C语言工程中,匈牙利命名法已经很少用了。我个人建议——除非团队有历史遗留代码,否则别主动引入。
三、驼峰命名法:Java风格,C语言能用吗?
驼峰命名法在Java、JavaScript里很常见。C语言里也能用,但要注意场合。
举个例子:
// 驼峰命名法
int totalCount = 0;
void getUserName(char *buffer) {
// ...
}
看起来挺清爽的,对吧?但我在嵌入式项目里吃过亏。有一次,我用驼峰命名法写了一个驱动模块,结果同事在review时直接说:「这看着像Java代码,不像C代码。」
为什么会这样?因为C语言社区的传统是下划线命名法。驼峰命名法在C语言里,容易让人感觉「不地道」。
我的建议:如果你在写纯C项目,尽量别用驼峰命名法。除非你用的是C++,或者团队明确约定用驼峰。
四、下划线命名法:C语言的正统选择
下划线命名法,是C语言社区最广泛接受的风格。Linux内核、FreeRTOS、各种嵌入式库,几乎都在用。
// 下划线命名法
int total_count = 0;
void get_user_name(char *buffer) {
// ...
}
你想想看,为什么C语言偏爱下划线?
- 可读性强:单词分隔清晰,一眼就能看出语义
- 与标准库一致:C标准库的函数都是下划线风格,比如
strcpy、memcpy - 避免冲突:驼峰命名法容易和C++的命名风格混淆
核心结论:在C语言工程化项目中,下划线命名法是默认选择。这不是个人喜好问题,而是社区共识。
五、我到底该用哪个?一张图说清楚
下面这张图,是我多年项目经验的总结。你可以把它当作决策参考。
六、避坑指南:我曾经踩过的坑
讲几个真实案例,希望能帮你少走弯路。
坑1:混用命名法
我曾经在一个项目里,看到同一个文件里既有userName又有user_name。结果呢?搜索的时候永远搜不全,重构时改一个漏一个。后来花了整整两天才把所有名字统一。
教训:一个项目只选一种命名法,写到编码规范里,严格执行。
坑2:匈牙利命名法滥用
有一次我接手一个老项目,里面全是匈牙利命名法。变量名长成这样:pstDeviceInfo、hModuleHandle、dwErrorCode。读代码时,前缀占了一半字符,真正有用的信息反而被淹没了。
教训:匈牙利命名法在C语言里已经过时了。除非你维护的是20年前的代码,否则别用。
坑3:驼峰命名法用在嵌入式C里
我有个朋友,在STM32项目里用了驼峰命名法。结果呢?和HAL库的下划线风格格格不入。每次看代码都要切换思维模式,特别累。
教训:嵌入式C项目,请坚持下划线命名法。和标准库保持一致,才是正道。
七、我的最终建议
说了这么多,给你一个可以直接用的结论:
C语言工程化项目 → 下划线命名法
这是最安全、最主流、最不容易出错的选择。
如果你在写C++,可以考虑驼峰命名法。
匈牙利命名法?嗯,忘掉它吧。
记住一句话:命名规范不是为了炫技,而是为了让代码更容易被理解。你想想看,三个月后的你,看到自己写的代码,能一眼看懂吗?
好了,这一章就到这里。命名规范是个大话题,但核心就一句话——选一个,坚持用。