一、总体原则
【描述】在保证功能正确的基础上,可读、可维护、安全、可靠、可测试、高效、可移植。
二、代码风格
【描述】代码风格指编写代码遵循的规则和约定,旨在提高代码的可读性、一致性、可维护性。
2.1、命名风格
【描述】一个标识符的好坏很大程度上取决于标识符名称。标识符命名应用合适长度完整、准确地描述其所代表的事务。
【规范】业界共四种命名法则:驼峰命名、匈牙利命名、帕斯卡命名、下划线命名,前三种较流行。
【注意】产品决定标识符命名风格。
- 推荐驼峰
- 亲和Linux/Unix的代码,可用内核风格
- 开源和外部代码,维持原风格
2.1.1、命名习惯
【规范】好的命名习惯包括但不限于:
- 使用正确的英文单词,并符合英文语法。不使用拼音。
- 使用单词缩写命名时,仅使用常见或领域通用。
- 对布尔型变量、函数名,避免用否定形式。
2.1.2、命名长度
【规范】不冲突、不过长过短,作用域越大,描述越精确。
2.2、排版风格
【规范】排版风格包括但不限于:
2.2.1、大括号
- K&R风格:函数大括号的左括号独占一行,其他类型大括号的左括号跟随语句放行末。右括号独占一行,除非后面跟着同一语句的剩余部分。
- Allman风格:左右大括号均独占一行。
2.2.2、行
- 行宽不超120字符。
- 一行只有一条语句。
- 换行时,新一行进行同类对其或缩进一层。
2.2.3、*
任何时候,*宜跟随变量名或函数名,除非右侧没有变量或函数名,可以跟随类型。
2.2.4、空格
- 行末不加
- 关键字(if、switch、do、while、for等)后加空格
- 小括号内部两侧不加
- 一元操作符后不加
- 二元操作符两侧都加
2.2.5、空行
根据内容的相关程度,合理安排空行。
2.3、注释风格
【规则】C语言按需写注释,有三种注释方式,前两种为常见:
- 以
/*
开始、以*/
结束的块注释(block comment)。用于单、多行注释,/**/不嵌套/**/,/**/可嵌套//。 - 以
//
开始、以换行符结束的单行注释(line comment)。 - 条件编译注释。
【规范】注释置于对应代码上方或右方。
- 上方注释应与代码同缩进,无空行。
- 右方注释应与代码至少留一个空格,与下一行注释左对齐。长度不宜过长,不应超过行宽。
【注意】注释内容也可能是存在格式的。
三、编程实践
3.1、宏
【规则】
- 宏名避免与关键字同名。
- 函数宏调用时,其参数不应出现预处理指令如#include、#define 、#ifdef。
- 宏定义不依赖宏外部的局部变量。
- 包含多条语句的函数式宏,必须放在do-while(0)中。
- 使用()。单独的数字、标识符无需(),负数需要(),
【规范】
- 函数式宏尽量不超过10行。
- 宏定义内容不以分号结尾。(易误用)
- 慎用return、goto、continue、break等语句。
- 使用函数代替函数式宏。宏缺乏类型检查,比函数更难调试和定位,。
【注意】带参数的宏容易出现问题。
3.2、头文件
【描述】每个.c应有一个对应的.h(不一定同名),用于放置对外提供的函数声明、类型定义、宏定义。
【规则】
- 仅在.c内部使用的函数在.c文件头部声明,用static限制作用域。
- 不包含用不到的头文件(减少不必要的依赖,降低模块与单元耦合度,避免编译时间恶化)。
- 自包含(即.h不包含其他的.h,避免包含顺序的依赖)、可独立编译。
- 使用#define进行包含保护。注意:保护符大写下划线分割、唯一命名,避免首尾是下划线。
- 禁止通过声明的方式引用外部函数接口、外部变量(隐式依赖,容易导致声明和定义不一致)。
- 按照稳定度包含头文件。依次是:C标准库、操作系统库、平台库、项目公共库、自己其他的依赖。
- 不在extern "C"中包含头文件。嵌套太多次extern "C"会导致编译错误。
【规范】不提倡一个.c有两个.h(一个放置对外相关、一个放置内部使用),无法从技术规避别人包含。
3.3、条件编译
【规则】
- #if或 #endif的预处理指令的常量表达式应该是布尔值,不直接使用0、1、2等。
- #if或 #endif的预处理指令的常量表达式被求值前应确保其使用的标识符已定义。
3.4、数据类型
【规则】除非有明确的必要性,否则避免重复定义基础类型。
【规范】避免隐式有损算数转换。
3.5、变量
【规则】
- 禁止将局部变量的地址传递到作用域外。
- 资源不再使用予以关闭、释放。
【规范】
慎用全局变量。