需求
-
稣希望保持手指的健康,尽量少敲击。
-
面对“这样可以,那样也可以”的规范,稣希望能贯彻某种原则,以减少内耗。
思考
以上两条在多数情况下是不矛盾的,所以就可以把第一条作为原则:尽量少敲击!
但要注意的是,本文讨论的是编码风格里最低级的议题——格式。所以它不涉及如何命名,比如说变量、函数的命名,应该贯彻可读性好的原则,别乱缩写。
“敲击少”的原则仅用于信息量完全一样的场景!
具体规则
1. 缩进 2 个空格即可
在视觉上 2 个空格已经足够分辨。
著名风格中,使用 2 个空格缩进的有:LLVM、Google、Chromium、GNU、Mozilla,用 4 个的只有:Microsoft 和 WebKit。可见 2 个才是主流。
ClangFormat 配置为:
1 | IndentWidth: 2 |
2. 左对齐节省空格
2.1 指针左对齐(PointerAlignment)
C++ 不像 Go、Rust 那样有“官方的”格式化风格,所以指针符号怎么对齐就有四种样式:
- 左:
int* p; - 右:
int *p; - 中:
int * p; - 哦不:
int*p;
著名风格主要分为两派:Google、Chromium、Mozilla、WebKit 使用左对齐,而 LLVM、GNU、Microsoft 使用右对齐。
作为规范制定者,淘汰掉最后一种是极其容易的——因为 ClangFormat 的 PointerAlignment 没有这个选项!而 Middle,则是因为没有著名风格使用,也应该被淘汰!
接下来,稣便利用“敲击少”的原则在“左”和“右”中二选一!注意到:在类型转换中,两者是不同的:
1 | void*p{}; |
在左样式时,被格式化为:
1 | void* p{}; |
而使用右样式,则被格式化为:
1 | void *p{}; |
可见右样式在类型转换场景下会比左样式多出一个空格,这违反了“敲击少”的原则,所以稣愉快地选择了左样式。
同理,ReferenceAlignment 应该和 PointerAlignment 一样,所以可以把其值设为 Pointer 或 Left。
em,本条还没完……还有一个 DerivePointerAlignment 应该设为 false。如果是 true,ClangFormat 会分析格式化文件,以确定最常见的 & 和 * 对齐方式。指针和引用对齐样式将根据文件中找到的首选项进行更新。然后,PointerAlignment 仅用作后备。
一份 .clang-format 的相关部分参考:
1 | DerivePointerAlignment: false |
2.2 AlignEscapedNewlines 左对齐
在转义的换行符中对齐反斜杠的选项。可能的值:
- DontAlign:不要对齐转义的换行符。(难看)
- Left:将转义的换行符尽可能左对齐。
- Right:将转义的换行符尽可能右对齐。(最好看,但空格更多)
AlignEscapedNewlines 使用 Left 的著名风格有:Google、Chromium,使用 Right 的有:LLVM、GNU、Microsoft、Mozilla、WebKit。
3. 在不影响可读性时,尽量少换行
通常来说,在语句块之间插入换行或注释,可以提高可读性。比如说:
1 | render_log_init(); |
如果把空行都去掉,就比较难一眼看清这些代码做了几件事。当然,如果每个语句块的开头都有注释,其实也可以不要空行,只不过注释可不是人人都爱写,并且,一些通过命名自注释的语句块,再写注释确实显得重复啰嗦。
但是,反转来了——有些地方换不换行不影响可读性。比如说 { 之前的换行、函数返回值类型后的换行……
3.1 BraceWrapping
事实上,缩进已经能保证可读性,{ 有没有和 } 垂直对齐,已经不重要。(每行不要太长更重要点!)
所以,在 .clang-format 的 BraceWrapping 节下面,应该越多 false/Never 越好,比如 Google 和 Chromium 都是:
1 | BraceWrapping: |
在著名风格里,论 { 之前省换行,Google 和 Chromium 是并列第一名。
3.2 BreakAfterReturnType
这个选项有 5 个可选样式值:
- None:自动
- All:总是在返回类型之后换行,包括定义和声明。
- TopLevel:总是在顶级函数的返回类型之后换行,包括定义和声明。
- AllDefinitions:总是在函数定义的返回类型之后换行。
- TopLevelDefinitions:总是在顶级定义的返回类型之后换行。
主流的著名风格使用 None,比如 LLVM、Google、Chromium、Microsoft、WebKit,只有两个例外:
- Mozilla 采用 TopLevel
- GNU 采用 AllDefinitions
结论
在“敲击少”原则的筛选下,著名风格里只有 Google、Chromium 生存下来。
扩展
-
《指针判空》时,应该省略和 nullptr 比较。
-
从机器的角度看“少”,应该把换行符指定为 LF,毕竟在 UTF-8 编码时,每行能省一字节。参考:《Git 换行符设置终极指南》
如果您使用微信,也可以关注公众号 UMU618,在公众号文章里评论。