通用C语言编码规范
目录
1. 总体原则
1.1 可读性优先
- 代码应该像散文一样易于阅读
- 清晰的命名比短小的命名更重要
- 一致性胜过个人偏好
1.2 简洁性
- 避免不必要的复杂性
- 一个函数只做一件事
- 避免过深的嵌套
1.3 安全性
- 检查所有输入参数
- 避免缓冲区溢出
- 明确处理错误情况
2. 命名约定
2.1 文件命名
1 2 3 4 5 6 7 8 9
| string_utils.c memory_pool.c uart_driver.c
string_utils.h memory_pool.h uart_driver.h
|
2.2 函数命名
2.2.1 公共函数 - snake_case
1 2 3 4
| int memory_pool_init(memory_pool_t *pool, size_t size); bool string_utils_is_empty(const char *str); void uart_driver_send_data(const uint8_t *data, size_t len);
|
2.2.2 静态函数 - snake_case + 前缀
1 2 3 4
| static bool _validate_parameters(const memory_pool_t *pool); static void _internal_cleanup(void); static int pool_find_free_block(memory_pool_t *pool, size_t size);
|
2.3 变量命名
2.3.1 局部变量 - snake_case
1 2 3 4
| int buffer_size; char *user_name; bool is_initialized; size_t total_count;
|
2.3.2 全局变量 - g_ 前缀
1 2 3
| static int g_instance_count = 0; extern bool g_system_ready; static memory_pool_t g_default_pool;
|
2.3.3 常量 - 大写字母
1 2 3 4 5
| [[define]] MAX_BUFFER_SIZE 1024 [[define]] DEFAULT_TIMEOUT_MS 5000
static const int MAX_RETRY_COUNT = 3; static const char* const ERROR_MESSAGES[] = {...};
|
2.3.4 函数指针
1 2 3 4 5 6
| typedef int (*error_handler_t)(int error_code); typedef void (*callback_func_t)(void *user_data);
error_handler_t error_handler; callback_func_t on_complete_callback;
|
2.4 类型命名
2.4.1 结构体 - _t 后缀
1 2 3 4 5 6 7 8 9 10 11
| typedef struct { size_t size; void *data; bool is_valid; } buffer_t;
typedef struct memory_pool { uint8_t *pool_start; size_t pool_size; size_t used_size; } memory_pool_t;
|
2.4.2 枚举 - _e 后缀, 成员大写
1 2 3 4 5 6 7 8 9 10 11 12 13
| typedef enum { STATUS_SUCCESS = 0, STATUS_ERROR_INVALID_PARAM, STATUS_ERROR_NO_MEMORY, STATUS_ERROR_TIMEOUT } status_e;
typedef enum { LOG_LEVEL_DEBUG = 0, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR } log_level_e;
|
2.4.3 联合体 - _u 后缀
1 2 3 4 5 6 7 8 9
| typedef union { uint32_t value; struct { uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; } bytes; } register_value_u;
|
3. 代码格式化
3.1 缩进和空格
1 2 3 4 5 6 7 8 9 10
| int main(void) { if (condition) { do_something(); if (another_condition) { do_more_work(); } } return 0; }
|
3.2 大括号风格 - K&R风格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int function_name(int param1, char *param2) { if (param1 > 0) { process_data(param2); } else { handle_error(); }
for (int i = 0; i < param1; i++) { work_with_index(i); }
return result; }
|
3.3 空行和空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| int process_data(const char *input) { int result = 0; char buffer[256];
if (!input) { return -1; }
result = parse_input(input, buffer, sizeof(buffer)); if (result < 0) { return result; }
return finalize_processing(buffer); }
int value = (a + b) * c; bool is_equal = (x == y); ptr->field = new_value; array[index] = item;
|
3.4 行长度
1 2 3 4 5 6 7 8 9 10 11 12
| int very_long_function_name(int first_parameter, const char *second_parameter, bool third_parameter, size_t fourth_parameter);
result = process_complex_data(input_buffer, buffer_size, &output_buffer, &output_size, processing_flags);
|
4. 函数设计
4.1 函数长度
- 函数应该简短,通常不超过50行
- 一个函数只做一件事
4.2 参数传递
1 2 3 4 5 6 7 8 9 10 11 12
| int string_length(const char *str);
int get_system_info(system_info_t *info);
int process_config(const config_t *config);
bool is_valid_address(const void *addr); bool has_permission(int user_id, int resource_id);
|
4.3 返回值约定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int memory_pool_alloc(memory_pool_t *pool, size_t size, void **ptr) { if (!pool || !ptr) { return -1; }
if (size == 0) { return -2; }
return 0; }
bool is_memory_available(const memory_pool_t *pool, size_t size) { if (!pool) { return false; }
return (pool->free_size >= size); }
|
5. 变量声明
5.1 声明位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int process_array(int *array, size_t count) { if (!array || count == 0) { return -1; }
for (size_t i = 0; i < count; i++) { int current_value = array[i];
if (current_value < 0) { return -2; }
array[i] = process_value(current_value); }
return 0; }
|
5.2 初始化
1 2 3 4 5 6 7 8
| int counter = 0; char *buffer = NULL; bool is_ready = false;
int values[5] = {0}; char name[32] = {0};
|
5.3 指针声明
1 2 3 4 5 6
| char *str_ptr; int *int_ptr; const char *const_str; char * const fixed_ptr; const char * const const_str_const_ptr;
|
6. 结构体和枚举
6.1 结构体设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| typedef struct { uint32_t id; uint16_t status; uint8_t flags; uint8_t reserved; void *data; } packet_header_t;
typedef struct memory_block { struct memory_block *next; size_t size; bool is_free; uint8_t data[]; } memory_block_t;
|
6.2 枚举设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| typedef enum { UART_BAUD_9600 = 9600, UART_BAUD_19200 = 19200, UART_BAUD_38400 = 38400, UART_BAUD_115200 = 115200 } uart_baud_e;
typedef enum { ERR_NONE = 0, ERR_INVALID_PARAM = -1, ERR_NO_MEMORY = -2, ERR_TIMEOUT = -3, ERR_NOT_INITIALIZED = -4 } error_code_e;
|
6.3 位域
1 2 3 4 5 6 7
| typedef struct { unsigned int enable : 1; unsigned int mode : 2; unsigned int priority : 4; unsigned int reserved : 25; } control_register_t;
|
7. 宏定义
7.1 简单宏
1 2 3
| [[define]] MAX_PATH_LENGTH 260 [[define]] PI 3.14159265359 [[define]] NULL_CHECK(ptr) ((ptr) != NULL)
|
7.2 函数式宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [[define]] DEBUG_PRINT(fmt, ...) \ do { \ if (debug_enabled) { \ printf("[DEBUG] " fmt "\n", ##__VA_ARGS__); \ } \ } while(0)
[[define]] MAX(a, b) (((a) > (b)) ? (a) : (b)) [[define]] MIN(a, b) (((a) < (b)) ? (a) : (b))
[[define]] ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
7.3 条件编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| [[ifndef]] STRING_UTILS_H [[define]] STRING_UTILS_H
[[ifdef]] __cplusplus extern "C" { [[endif]]
[[ifdef]] DEBUG [[define]] DBG_ASSERT(expr) \ do { \ if (!(expr)) { \ fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", \ [[expr]], __FILE__, __LINE__); \ abort(); \ } \ } while(0) [[else]] [[define]] DBG_ASSERT(expr) ((void)0) [[endif]]
[[ifdef]] __cplusplus } [[endif]]
[[endif]]
|
8. 注释规范
8.1 文件头注释
8.2 函数注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
int memory_pool_init(memory_pool_t *pool, void *buffer, size_t size, size_t block_size);
|
8.3 行内注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| int process_data(const uint8_t *data, size_t len) { if (!data || len == 0) { return -1; }
uint32_t checksum = 0;
for (size_t i = 0; i < len; i++) { checksum += data[i]; }
checksum = ~checksum + 1;
[[ifdef]] LITTLE_ENDIAN checksum = __builtin_bswap32(checksum); [[endif]]
return (int)checksum; }
|
8.4 TODO和FIXME
9. 文件组织
9.1 头文件结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| [[ifndef]] MODULE_NAME_H [[define]] MODULE_NAME_H
[[include]] <stdio.h> [[include]] <stdlib.h> [[include]] <string.h>
[[include]] <sys/types.h> [[include]] <unistd.h>
[[include]] "project_config.h" [[include]] "common_types.h"
[[include]] "module_internal.h"
[[ifdef]] __cplusplus extern "C" { [[endif]]
[[define]] MODULE_VERSION "1.0.0" [[define]] MAX_BUFFER_SIZE 1024
typedef struct module_context module_context_t;
typedef enum { MODULE_STATE_IDLE, MODULE_STATE_BUSY, MODULE_STATE_ERROR } module_state_e;
typedef struct { int id; char name[32]; module_state_e state; } module_info_t;
int module_init(module_context_t **ctx); int module_process(module_context_t *ctx, const void *input); void module_cleanup(module_context_t *ctx);
[[ifdef]] __cplusplus } [[endif]]
[[endif]]
|
9.2 源文件结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
[[include]] "module_name.h" [[include]] "module_private.h"
[[define]] INTERNAL_BUFFER_SIZE 256 [[define]] RETRY_COUNT 3
typedef struct { uint8_t internal_buffer[INTERNAL_BUFFER_SIZE]; size_t buffer_used; bool is_initialized; } module_private_t;
static module_private_t g_module_data = {0}; static bool g_module_initialized = false;
static int _validate_input(const void *input); static void _cleanup_internal_data(void);
int module_init(module_context_t **ctx) { }
static int _validate_input(const void *input) { }
|
10. 错误处理
10.1 错误码定义
1 2 3 4 5 6 7 8 9 10 11 12 13
| typedef enum { ERR_SUCCESS = 0, ERR_INVALID_PARAM = -1, ERR_NULL_POINTER = -2, ERR_NO_MEMORY = -3, ERR_BUFFER_OVERFLOW = -4, ERR_TIMEOUT = -5, ERR_NOT_FOUND = -6, ERR_ALREADY_EXISTS = -7, ERR_NOT_INITIALIZED = -8, ERR_OPERATION_FAILED = -9 } error_code_e;
|
10.2 参数检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| int safe_function(const char *input, char *output, size_t output_size) { if (!input) { return ERR_NULL_POINTER; }
if (!output) { return ERR_NULL_POINTER; }
if (output_size == 0) { return ERR_INVALID_PARAM; }
size_t input_len = strlen(input); if (input_len >= output_size) { return ERR_BUFFER_OVERFLOW; }
strcpy(output, input);
return ERR_SUCCESS; }
|
10.3 错误传播
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int complex_operation(const char *file_path, data_t *result) { int error; file_handle_t handle;
error = file_open(file_path, &handle); if (error != ERR_SUCCESS) { return error; }
error = file_read(handle, result); if (error != ERR_SUCCESS) { file_close(handle); return error; }
error = file_close(handle); return error; }
|
11. 内存管理
11.1 动态内存分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| void* safe_malloc(size_t size) { if (size == 0) { return NULL; }
void *ptr = malloc(size); if (ptr) { memset(ptr, 0, size); }
return ptr; }
void safe_free(void **ptr) { if (ptr && *ptr) { free(*ptr); *ptr = NULL; } }
char *buffer = (char*)safe_malloc(256); if (!buffer) { return ERR_NO_MEMORY; }
}
safe_free((void**)&buffer);
|
11.2 缓冲区安全
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| int safe_strcpy(char *dest, size_t dest_size, const char *src) { if (!dest || !src || dest_size == 0) { return ERR_INVALID_PARAM; }
size_t src_len = strlen(src); if (src_len >= dest_size) { return ERR_BUFFER_OVERFLOW; }
memcpy(dest, src, src_len); dest[src_len] = '\0';
return ERR_SUCCESS; }
int safe_append(char *buffer, size_t buffer_size, const char *text) { if (!buffer || !text || buffer_size == 0) { return ERR_INVALID_PARAM; }
size_t current_len = strnlen(buffer, buffer_size); size_t text_len = strlen(text);
if (current_len + text_len + 1 > buffer_size) { return ERR_BUFFER_OVERFLOW; }
strcat(buffer, text);
return ERR_SUCCESS; }
|
12. 最佳实践总结
12.1 代码质量检查清单
12.2 性能考虑
- 避免在循环中进行昂贵操作
- 合理使用const关键字
- 考虑内存对齐
- 最小化函数调用开销
12.3 可维护性
- 保持函数简短
- 避免深层嵌套
- 使用有意义的变量名
- 模块化设计
12.4 可移植性
- 避免依赖特定编译器扩展
- 使用标准C库函数
- 考虑字节序问题
- 使用配置宏处理平台差异
附录:常用工具
A.1 静态分析工具
cppcheck - 静态代码分析
clang-tidy - 代码质量检查
splint - 代码注释检查
A.2 格式化工具
clang-format - 自动代码格式化
indent - GNU缩进工具
A.3 内存检查工具
valgrind - 内存泄漏检测
AddressSanitizer - 地址检查
static analysis - 静态内存分析
本编码规范遵循业界最佳实践,适用于一般性C语言项目开发。