C 语言企业级命名规范 作者:马育民 • 2026-04-08 08:50 • 阅读:10001 # 介绍 良好的命名规范是工程化 C 项目的基石。本文基于**嵌入式、Linux、驱动、后台服务**等企业级项目通用实践,整理一套可落地、无歧义、团队可直接执行的命名规则。 ### 结论先行 这套规范核心原则: - 统一风格,不混用 - 全局变量 `g_`、静态变量 `s_`、指针 `p_` - 常量全大写,类型大驼峰 - 变量、普通函数小写下划线 - 全局函数:普通函数前面加 `模块名_` 命名规范的本质不是约束,而是**降低沟通成本、提升可维护性**。 # 1 通用硬性规则 1. 标识符只能由:**英文字母、数字、下划线**组成 2. 不能以数字开头 3. 严格区分大小写 4. 不能使用 C 语言关键字(`int`/`char`/`if`/`else`/`enum`/`struct` 等) 5. 文件名统一:**小写 + 下划线** - 例:`main.c`、`uart_driver.c`、`sensor_config.h` 6. 禁止拼音、中文、无意义缩写(`a`/`b`/`tmp` 仅允许极短期临时变量) 7. 禁止**下划线与驼峰混用**,项目全局统一一种风格 --- # 2 推荐统一风格(企业最常用) C 语言主流风格:**下划线命名法(snake_case)** - 变量、函数、文件:`student_count`、`uart_init` - 宏、枚举常量:**全大写 + 下划线** - 结构体/typedef:**大驼峰(PascalCase)** --- # 3 变量命名规范 ## 3.1 局部变量 - 小写 + 下划线 - 见名知意,简洁清晰 ```c int count; int buffer_len; char user_name[32]; ``` ## 3.2 全局变量 - 规则:**必须加 `g_` 前缀** - 目的:一眼识别全局,避免与局部变量冲突 ```c int g_system_status; int g_uart_fd; char g_recv_buffer[1024]; ``` ## 3.3 静态全局 / 静态局部变量 - 规则:加 `s_` 前缀 ```c static int s_init_flag; static int s_cache_size; ``` ## 3.4 指针变量 - 建议加 `p_` 前缀,明确是指针 ```c char *p_data; int *p_len; struct Student *p_stu; ``` ## 3.5 布尔/状态标志 - 以 `is_`/`has_`/`enable_` 开头 ```c int is_ready; int has_error; int enable_uart; ``` --- # 4 常量与宏 ## 4.1 `#define` 宏 - 全大写 + 下划线 ```c #define MAX_BUFFER_SIZE 1024 #define UART_BAUDRATE 115200 ``` ## 4.2 `const` 常量 - 推荐同宏风格:全大写 + 下划线 ```c const int MAX_CLIENT_NUM = 10; const char DEVICE_NAME[] = "uart0"; ``` --- # 5 函数命名 - 小写 + 下划线 - 动词开头,语义清晰 ```c void system_init(void); int uart_send(const char *p_data, int len); int sensor_get_value(void); ``` - 静态函数:可加模块前缀,避免污染全局命名空间 ```c static int check_param_valid(int param); ``` --- ## 全局函数 **全局函数 = 模块名前缀 + 下划线 + 功能名** 这是**嵌入式 / Linux / 驱动 / 后台服务**最标准的写法。 ### 格式 ```c 返回值 模块名_功能名(参数); ``` ### 示例 ```c // UART 模块 void uart_init(void); int uart_send_data(char *buf, int len); // LED 模块 void led_on(void); void led_off(void); // 系统模块 void system_reset(void); int system_get_version(void); ``` --- ### 为什么要加模块前缀? 因为**全局函数是整个工程可见的**。 不加前缀,很容易出现**函数重名冲突**! 例如: ```c // 两个文件都写 init() → 编译报错!重复定义 void init(void); ``` 所以企业规范强制: **全局函数必须带模块前缀** # 6 结构体、枚举、typedef ## 6.1 结构体 - 大驼峰 ```c typedef struct { int id; char name[32]; int age; } StudentInfo; ``` ## 6.2 枚举 - 类型:大驼峰 - 枚举值:全大写 + 下划线 ```c typedef enum { STATUS_OK = 0, STATUS_ERROR_PARAM, STATUS_ERROR_TIMEOUT } StatusCode; ``` ## 6.3 类型别名 - 大驼峰 ```c typedef unsigned char Uint8; typedef unsigned int Uint32; ``` --- # 7 企业编码红线 1. 禁止单个字符命名(循环变量 `i/j/k` 除外) 2. 禁止下划线与驼峰混用 3. 禁止中文、拼音、特殊符号 4. 全局变量必须加 `g_` 前缀,禁止裸奔 5. 宏、枚举常量必须全大写 6. 禁止无意义函数名:`fun()`/`test()`/`do_something()` 7. 同一项目大小写混乱:`Uart`/`uart`/`UART` 混用 8. 禁止使用下划线开头命名(易与系统内部符号冲突) --- # 8 完整示例 ```c #include #define MAX_STUDENT 50 typedef enum { STATUS_OK = 0, STATUS_ERROR } StatusCode; typedef struct { int id; char name[32]; } StudentInfo; static int s_student_count = 0; int g_system_running = 1; StatusCode add_student(StudentInfo *p_stu) { if (s_student_count >= MAX_STUDENT) { return STATUS_ERROR; } s_student_count++; return STATUS_OK; } int main(void) { StudentInfo stu = {1, "zhangsan"}; StatusCode ret = add_student(&stu); printf("ret = %d\n", ret); return 0; } ``` # 单片机常用大驼峰 因为: - STM32 HAL/LL库:`HAL_GPIO_TogglePin()` - Arduino:`digitalWrite()` - RT-Thread:`rtDeviceFind()` - Keil、ARM 官方示例:大量大驼峰 这些库为了**辨识度高、和底层 C 区分开**,普遍使用: **大驼峰 / 小驼峰** 所以: **单片机项目用驼峰,完全正确、非常常见。** --- ### 哪种命名是对的? 一句话总结:**没有唯一正确,只有“项目统一”。** 但行业有两大主流派系: ##### 派系1:Linux / 驱动 / 底层 C → 下划线 snake_case - 全局函数:`uart_init()` - 变量:`rx_buffer_len` ##### 派系2:单片机 / STM32 / Arduino / 嵌入式GUI → 驼峰 - 全局函数:`UartInit()`、`halGpioInit()` - 变量:`rxBufferLen` --- ### 如果项目偏底层 / Linux / 裸机驱动 → 用 **下划线** ```c void uart_init(void); int g_system_status; ``` ### 如果项目基于 STM32 HAL / Arduino / RTOS → 跟随库风格,用 **驼峰** ```c void Uart_Init(void); void UartInit(void); int gSystemStatus; ``` 原文出处:http://malaoshi.top/show_1GW35n7rHTTy.html