C/C++语言编程规范(一)

发布时间:2026/5/22 16:54:07

C/C++语言编程规范(一) 0. 引言最近博主在做嵌入式AI相关的边缘部署项目目前项目已经完成一大半但是随着代码量的不断迭代团队协作中的代码混乱问题逐渐凸显。不同成员的命名风格不一、排版格式杂乱不仅导致代码可读性大幅下降后期调试、维护时也耗费了大量时间甚至出现因命名不规范引发的逻辑漏洞。基于此结合项目实战经验整理一份详细的代码命名与格式规范涵盖命名原则、排版要求等核心内容希望能帮助同行规避同类问题提升代码质量与协作效率。1. 命名规范1.1 命名通用核心原则用完整单词 / 通用缩写项目内仅选一种风格Unix like小写下划线如user_nameWindows驼峰如userName禁止新代码用匈牙利命名法如iUser/szName反义词组统一互斥含义的变量/函数用固定反义词如add/remove、open/close、create/destroy避免数字编号除非逻辑必需如step1禁止test1/test2这类无意义编号用语义命名替代1.2 文件命名规则公司规范强制推荐Unix like 风格适配跨平台开发Linux区分大小写、Windows不区分核心要求全小写字母单词间用下划线分隔禁止加模块/产品前缀如sys_/cvte_避免文件移植时重命名头文件用.h后缀禁止.inc等非标准后缀兼容IDE/静态检查工具文件命名规范错误对照反面示例错误正面示例正确错误原因UserInfo.c、TEST_FILE.huser_info.c、test_file.h大小写混合不符合跨平台规范sys_login.c、cvte_config.hlogin.c、config.h加了模块前缀移植性差data.incdata.h非标准后缀IDE 无法识别拓展模块级文件建议按功能归类如timer_init.c/timer_drv.h同模块文件前缀统一语义相关非强制前缀1.3 变量命名规则命名结构建议名词 / 形容词 名词体现变量含义全局变量加g_前缀醒目提醒减少滥用如g_sys_running静态变量文件内私有加s_前缀如s_module_count局部变量无前缀禁止单字节命名除i/j/k作为循环变量禁止匈牙利命名法变量名体现含义而非类型如不用iCount/szName用count/user_name// 全局变量g_前缀 语义命名intg_device_status;// 设备状态charg_server_ip[64];// 服务器IP// 静态变量s_前缀 语义命名staticints_packet_num;// 包计数文件内私有voidfunc(){// 局部变量无前缀形容词名词禁止单字节i/j/k除外intvalid_flag0;// 有效标志charrecv_buff[128];// 接收缓冲区// 循环变量允许i/j/kfor(inti0;i10;i){// 业务逻辑}}1.4 函数命名规则核心要求以动作命名结构建议动词 / 动词 名词体现函数行为普通函数动词名词如read_file、init_timer、check_param函数指针按普通函数命名可加pfn_前缀项目内统一即可如pfn_event_callback接口函数对外暴露语义更明确避免缩写除通用缩写如device_get_status而非dev_get_sta文件内私有函数加static修饰命名同普通函数如static void free_buff()1.5 宏 / 常量命名规则宏和常量是只读值命名需与变量/函数区分核心规则分普通宏/常量和特殊宏编译开关/头文件保护两类普通宏/常量数值/字符串/枚举全大写单词间用下划线分隔如MAX_BUFFER_LEN、PI编译开关宏全大写加ENABLE_/DISABLE_/CFG_前缀如ENABLE_LOG、CFG_TIMEOUT_SEC头文件保护宏全大写按PROJECT_MODULE_FILE_H格式保证唯一性如DEMO_TIMER_TIMER_H禁止宏用下划线开头/结尾系统保留下划线标识如STDIO_H常量优先用const定义而非宏有类型检查调试更友好// 1. 普通宏全大写下划线#defineMAX_BUFFER_LEN1024// 最大缓冲区长度#definePI3.1415926// 圆周率#defineTIME_OUT_SEC60// 超时时间秒// 2. 编译开关宏加前缀语义明确#defineENABLE_LOG1// 启用日志#defineDISABLE_DEBUG0// 禁用调试#defineCFG_UART_BAUD115200// 串口波特率配置// 3. 头文件保护宏项目_模块_文件_H#ifndefDEMO_UART_UART_H#defineDEMO_UART_UART_H// 头文件内容#endif// 4. 枚举全大写下划线同宏命名enumERROR_CODE{ERR_SUCCESS0,ERR_PARAM1,ERR_FILE2,ERR_NET3};// 5. const常量优先于宏有类型检查constintMAX_USER_NUM100;// 最大用户数constchar*DEFAULT_IP192.168.1.1;// 默认IP1.6 命名易踩坑补充规则公司规范重点强调通用缩写统一仅使用业界公认缩写禁止自定义缩写公司规范明确的通用缩写如下arg(argument)、buf(buffer)、cfg(configuration)、dev(device)、err(error)init(initialize)、max(maximum)、min(minimum)、msg(message)、para(parameter)避免名字冲突全局函数/宏避免用通用名如read/write/init加模块语义如uart_read/timer_init重构代码保持风格修改老代码时不强行修改原有命名风格仅新增代码按规范来保证文件内风格统一平台适配代码风格统一驱动/外购芯片代码保持与原平台命名风格一致如Linux驱动用snake_case不强行修改Unix/Linux平台snake_case小写下划线适配Linux内核/驱动开发如user_info、read_fileWindows平台CamelCase小驼峰适配Windows SDK如userInfo、readFile2. 保证质量2.1. 条件判断需完整覆盖避免逻辑漏洞核心要求所有if...else if结构必须以else结尾覆盖默认场景switch语句必须有default分支处理未定义的case值错误示例// 错误缺失elsescore 60时无返回值行为未定义intget_score_grade(intscore){if(score90)return1;elseif(score80)return2;elseif(score60)return3;}正确示例// 正确覆盖所有场景intget_score_grade(intscore){if(score90)return1;elseif(score80)return2;elseif(score60)return3;elsereturn4;// 覆盖score 60的场景}// switch必须带defaultswitch(cmd){caseCMD_A:process_A();break;caseCMD_B:process_B();break;default:process_default();break;// 覆盖未定义cmd}2.2. 避免滥用goto语句保证代码结构性goto会破坏代码顺序执行逻辑导致可读性差、维护困难仅允许一种场景使用允许场景统一释放资源的出口如内存、文件句柄释放禁止场景跨函数、跨代码块跳转或用于简化循环/条件判断3. 排版与格式3.1. 关键排版规则3.1.1 缩进4个空格禁用硬TAB每级缩进严格使用4个空格IDE需开启“TAB自动转空格”宏定义、编译开关#if/#else/#endif可顶格书写或与代码保持一致缩进项目内统一即可IDE向导生成的代码可保留默认格式无需强制修改if(ab){// 4个空格缩进printf(a大于b);for(inti0;i10;i){// 嵌套再缩进4个空格共8个sumi;}}// 宏定义顶格允许#defineMAX_LEN1024#ifDEBUG// 编译开关内缩进4个空格与代码一致printf(调试模式);#endif3.1.2 空行分隔独立逻辑块提升结构感相对独立的程序块之间必须加空行函数定义之间、变量声明与业务代码之间、不同逻辑段之间函数内部变量声明后需加空行再写执行语句空行仅用1行禁止连续多空行#includestdio.h#includestring.h// 全局变量声明后加空行intg_global_val0;// 函数之间加空行voidfunc1(){// 变量声明后加空行inta10;charbuf[32];// 逻辑段之间加空行strcpy(buf,test);printf(buf: %s\n,buf);if(a5){printf(a5\n);}}voidfunc2(){printf(func2\n);}3.1.3 换行长语句拆分避免横向滚动一条语句长度超过132字符必须换行换行后增加1级缩进4个空格换行优先在低优先级操作符后拆分、||、、操作符保留在新行首函数参数过多时每行写1个参数对齐方式统一禁止将多个短语句写在同一行// 长条件语句换行在后拆分新行缩进4个空格if((temp_flagTEST_FLAG)((temp_cnt-TEST_CNT_BEGIN)%TEST_CNT_MODTEST_CNT_THRESHOLD)){process();}// 长函数参数换行每行1个参数左对齐intcalc_sum(inta,intb,intc,intd){returnabcd;}// 长赋值语句换行在后拆分intresult(a*10b*5)(c*3-d*2);3.1.4 语句布局关键字独占一行代码块用{}包裹if、for、while、switch、case、default等关键字必须独占一行后面加空格再接括号代码块必须用{}包裹即使只有一行代码{的位置紧跟关键字后空格分隔或独占下一行项目统一即可case、default需缩进1级4个空格// 风格1{紧跟关键字后if(ab){printf(ab\n);}elseif(ab){printf(ab\n);}else{printf(ab\n);}// 风格2{独占下一行for(inti0;i10;i){sumi;}// switch-case规范布局switch(cmd){caseCMD_A:process_a();break;caseCMD_B:process_b();break;default:process_default();break;}3.1.5 空格优化可读性避免代码拥挤双目操作符、-、*、/、、、、||前后必须加1个空格单目操作符!、~、、--、、*前后不加空格逗号,、分号;后加1个空格前面不加括号内侧不加空格关键字与括号之间加1个空格如if (a)而非if(a)结构体/指针的.、-前后不加空格// 双目操作符前后加空格inta1020;if(a30b!0){a*2;}// 单目操作符前后不加空格int*pa;if(!is_empty){p;}// 逗号后加空格func(a,b,c);// 关键字与括号之间加空格for(inti0;i10;i){printf(%d\n,i);}// .和-前后不加空格structStudentstu;stu.namezhangsan;printf(name: %s\n,stu.name);printf(age: %d\n,p-age);3.1.6 其他格式规则多行宏需用\连接\后无空格换行后缩进4个空格#defineCALC(a,b)\((a)(b)*2)注释符与内容之间加1个空格// 注释内容而非//注释内容指针*与变量名对齐int *p而非int* p3.2. 常见排版误区总结编码规范常见排版误区对照表误区类型错误示例正确示例缩进不一致混用空格 TABif (ab) { printf(ab); }TAB2 空格if (ab) { printf(ab); }统一 4 个空格连续多空行int a 10;\n\n\nprintf(a%d, a);int a 10;\nprintf(a%d, a);长语句不换行if ((a1)(b2)(c3)(d4)) { process(); }if ((a1)(b2)(c3)(d4)) { process(); }一行多语句int a10; int b20; printf(a%d, a);int a10;int b20;printf(a%d, a);操作符前后无空格abc; if(ab)a b c; if (a b)

相关新闻