Clang-format格式化C代码
Author:Once Day Date:2022年11月3日
漫漫长路有人对你微笑过嘛…
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。人工智能学习网站 - 点击跳转。
参考文档:
- Clang-Format Style Options — Clang 16.0.0git documentation (llvm.org)
- ClangFormat — Clang 16.0.0git documentation (llvm.org)
- clang-format的介绍和使用 - Tudou_Blog - 博客园 (cnblogs.com)
文章目录
- Clang-format格式化C代码
- 1.引言
- 2. 配置字段解释
- 2.1 language 编程语言
- 2.2 BaseOnStyle 基础风格
- 2.3 AccessModifierOffset 访问性修饰符偏移
- 2.4 AlignAfterOpenBracket 开括号后的对齐
- 2.5 AlignArrayOfStructures 对齐结构体数组
- 2.6 AlignConsecutiveAssignments 对齐连续赋值
- 2.7 AlignConsecutiveBitFields 位段对齐
- 2.8 AlignConsecutiveDeclarations 连续声明对齐
- 2.9 AlignConsecutiveMacros 连续宏定义对齐
- 2.10 AlignEscapedNewlines 对齐分割语法行的斜杠符`\`
- 2.11 AlignOperands 竖直对齐表达式的操作数
- 2.12 AlignTrailingComments 对齐尾部注释
- 2.13 AllowAllArgumentsOnNextLine 允许参数在下一行上
- 2.14 AllowAllConstructorInitializersOnNextLine 已弃用
- 2.15 AllowAllParametersOfDeclarationOnNextLine 允许声明的参数在下一行上
- 2.16 AllowShortBlocksOnASingleLine 允许短语法块在单行上
- 2.17 AllowShortEnumsOnASingleLine 允许短枚举在单行上
- 2.18 AllowShortFunctionsOnASingleLine 允许短函数在单行上
- 2.19 **AllowShortIfStatementsOnASingleLine** 允许if块在单行上
- 2.20 AllowShortLambdasOnASingleLine 允许短匿Lambda函数在单行上
- 2.21 AllowShortLoopsOnASingleLine 允许合并短循环到单行上
- 2.22 AlwaysBreakAfterDefinitionReturnType 函数定义返回类型换行风格
- 2.23 AlwaysBreakAfterReturnType 函数声明的返回类型换行风格
- 2.24 AlwaysBreakBeforeMultilineStrings 多行字符串断行
- 2.25 AlwaysBreakTemplateDeclarations 模板声明断行
- 2.26 AttributeMacros 属性宏
- 2.27 BinPackArguments 装箱变量
- 2.28 BinPackParameters 装箱声明参数
- 2.29 BitFieldColonSpacing 位段列的空白风格
- 2.30 BraceWrapping 大括号换行风格
- 2.31 BreakAfterJavaFieldAnnotations 在修饰器之后断行
- 2.32 BreakArrays Json数组断行
- 2.33 BreakBeforeBinaryOperators 二元操作符断行
- 2.34 BreakBeforeBraces 大括号断行风格
- 2.35 BreakBeforeConceptDeclarations 概念声明断行风格
- 2.36 BreakBeforeTernaryOperators 三元操作符断行规则
- 2.37 BreakConstructorInitializers 构造初始化断行风格
- 2.38 BreakInheritanceList 继承链断行风格
- 2.39 BreakStringLiterals 字符串常量断行
- 2.40 ColumnLimit 列数限制
- 2.41 CommentPragmas 注释表示
- 2.42 CompactNamespaces 紧凑命名空间
- 2.43 ConstructorInitializerAllOnOneLineOrOnePerLine 构造初始化断行风格
- 2.44 ConstructorInitializerIndentWidth 构造初始化缩进宽度
- 2.45 ContinuationIndentWidth
- 2.46 Cpp11BracedListStyle 大括号列表风格
- 2.47 DeriveLineEnding 提取行结尾
- 2.48 DerivePointerAlignment 提取指针对齐
- 2.49 DisableFormat 禁用格式化
- 2.50 EmptyLineAfterAccessModifier 访问修饰符后空行
- 2.51 EmptyLineBeforeAccessModifier 访问修饰符前空行
- 2.52 ExperimentalAutoDetectBinPacking
- 2.53 FixNamespaceComments 修复命名空间描述
- 2.54 ForEachMacros 迭代循环宏
- 2.55 IfMacros 条件判断宏
- 2.56 IncludeBlocks `include`块风格
- 2.57 IncludeCategories `include`种类
- 2.58 IncludeIsMainRegex 判断主包含的正则表达式
- 2.59 IncludeIsMainSourceRegex 判断源文件的正则表达式
- 2.60 IndentAccessModifiers 访问修饰符缩进
- 2.61.1 IndentCaseBlocks `case`块缩进
- 2.61.2 **IndentCaseLabels** `case label`标签缩进
- 2.62 IndentExternBlock `Extern`扩展块缩进
- 2.63 IndentGotoLabels 缩进`Goto`跳转符号
- 2.64 IndentPPDirectives 预处理指令缩进
- 2.65 IndentRequiresClause 缩进要求子句
- 2.66 IndentWidth 缩进宽度
- 2.67 IndentWrappedFunctionNames 函数名缩进
- 2.68 InsertBraces 插入括号
- 2.69 InsertTrailingCommas 掺入尾部冒号
- 2.70 JavaImportGroups
- 2.71 JavaScriptQuotes Java引号风格
- 2.72 JavaScriptWrapImports `import/export`语句换行
- 2.73 KeepEmptyLinesAtTheStartOfBlocks 在语法块开始留空行
- 2.74 LambdaBodyIndentation Lambda表达式主体缩进
- 2.75 Language 目标格式化编程语言
- 2.76 MacroBlockBegin 开始块的宏
- 2.77 MacroBlockEnd 结束块的宏
- 2.78 MaxEmptyLinesToKeep 最大持续空行
- 2.79 NamespaceIndentation 命名空间缩进
- 2.80 NamespaceMacro 命名空间宏
- 2.81 ObjCBinPackProtocolList Objective-C打包风格
- 2.82 ObjCBlockIndentWidth ObjC块缩进
- 2.83 ObjCBreakBeforeNestedBlockParam 分解嵌套块参数
- 2.84 ObjCSpaceAfterProperty 属性修饰符空格
- 2.85 ObjCSpaceBeforeProtocolList 协议列表前空白
- 2.86 PPIndentWidth 预处理符号缩进指定
- 2.87 PackConstructorInitializers 打包构造器初始化列表
- 2.88 PenaltyXxxx 各类情况的惩罚
- 2.89 PointerAlignment 指针对齐风格
- 2.90 QualifierAlignment 限定符对齐
- 2.91 QualifierOrder 说明/限定符顺序
- 2.92 RawStringFormats 原始字符串格式
- 2.93 ReferenceAlignment 引用对齐格式
- 2.94 ReflowComments 重排版注释
- 2.95 RemoveBracesLLVM 移除括号
- 2.96 RemoveSemicolon 移除分号
- 2.97 RequiresClausePosition 要求子句位置
- 2.98 RequiresExpressionIndentation `require`表达式缩进
- 2.99 SeparateDefinitionBlocks 分离定义语句块
- 2.100 ShortNamespaceLines 短命名空间的行数
- 2.101 SortIncludes 对inclue排序
- 2.102 SortJavaStaticImport 排序java静态导入
- 2.103 SortUsingDeclarations 对using声明排序
- 2.104 SpaceAfterCStyleCast c风格类型转换
- 2.105 SpaceAfterLogicalNot 逻辑`!`操作符
- 2.106 SpaceAfterTemplateKeyword 模板关键字
- 2.107 SpaceAroundPointerQualifiers 指针限定符空格
- 2.108 SpaceBeforeAssignmentOperators 赋值操作符空格
- 2.109 SpaceBeforeCaseColon `case`前空格
- 2.110 SpaceBeforeCpp11BracedList 大括号列表空格
- 2.111 SpaceBeforeCtorInitializerColon 构造器初始化冒号空格
- 2.112 SpaceBeforeInheritanceColon 继承冒号空格
- 2.113 SpaceBeforeParens 圆括号空格
- 2.114 SpaceBeforeParensOptions 圆括号前空格控制
- 2.115 SpaceBeforeRangeBasedForLoopColon 循环范围里的冒号
- 2.116 SpaceBeforeSquareBrackets 方括号前空格
- 2.117 SpaceInEmptyBlock 空块中的空格
- 2.118 SpaceInEmptyParentheses 圆括号之间的空格
- 2.119 SpacesBeforeTrailingComments 尾部注释之前的空格
- 2.120 SpacesInAngles 角括号空白
- 2.121 SpacesInCStyleCastParentheses C`cast`转换里的空格
- 2.122 SpacesInConditionalStatement 条件表达式中的空白
- 2.123 SpacesInContainerLiterals 容器中空格
- 2.124 SpacesInLineCommentPrefix 行注释前缀空格
- 2.125 SpacesInParentheses 在圆括号里面的空格
- 2.126 SpacesInSquareBrackets 方括号之中的空白
- 2.127 Standard C++标准
- 2.128 StatementAttributeLikeMacros
- 2.129 StatementMacros
- 2.130 TabWidth Tab的宽度,替换为空白字符
- 2.131 TypenameMacros 类型名宏定义
- 2.132 UseCRLF 换行符种类
- 2.133 UseTab Tab的使用
- 2.134 WhitespaceSensitiveMacros
- 3. 结束
- 2.121 SpacesInCStyleCastParentheses C`cast`转换里的空格
- 2.122 SpacesInConditionalStatement 条件表达式中的空白
- 2.123 SpacesInContainerLiterals 容器中空格
- 2.124 SpacesInLineCommentPrefix 行注释前缀空格
- 2.125 SpacesInParentheses 在圆括号里面的空格
- 2.126 SpacesInSquareBrackets 方括号之中的空白
- 2.127 Standard C++标准
- 2.128 StatementAttributeLikeMacros
- 2.129 StatementMacros
- 2.130 TabWidth Tab的宽度,替换为空白字符
- 2.131 TypenameMacros 类型名宏定义
- 2.132 UseCRLF 换行符种类
- 2.133 UseTab Tab的使用
- 2.134 WhitespaceSensitiveMacros
- 3. 结束
1.引言
Clang-format是一种代码格式化工具,可以用来格式化各种代码,可以支持以下语言:
C/C++/Java/JavaScript/Objective-C/Protobuf/C#
此外,也可以使用prettier
,但是其对c语言支持有限。
使用方法如下:
USAGE: clang-format [options] [<file> ...]
更多的信息可以查找使用帮助。正常来说,使用以下命令就够了:
clang-format -style=可选格式名 [-i] main.c
上面即可根据指定的格式对指定的文件进行格式化,默认的格式有以下种类:
LLVM
A style complying with the LLVM coding standardsGoogle
A style complying with Google’s C++ style guideChromium
A style complying with Chromium’s style guideMozilla
A style complying with Mozilla’s style guideWebKit
A style complying with WebKit’s style guideMicrosoft
A style complying with Microsoft’s style guideGNU
A style complying with the GNU coding standards
此外还可以指定为InheritParentConfig
,表示继承上一级父文件夹内的.clang-format
配置,甚至可以指定继承其中的一部分:--style={BaseOnStyle:InheritParentConfig, ColumnLimit:20}
。
此外可以指定风格为-style=file
,表示使用自定义的配置文件。
Clang-format的配置文件可以取名为.clang-format
或者_clang-format
。该文件可以放在根目录或者最近的父目录,Clang-format都会自己去尝试寻找配置文件。
也可以直接指定配置文件的完整路径:-style=file:<format_file_path>
。
下面命令导出配置文件,以此为基础进行自定义(.clang-foramt)
clang-format -style=可选格式名 -dump-config > .clang-format
.clang-format
配置文件使用YAML
格式,如下:
key1: value1
key2: value2
#A comment
...
可以在配置文件时,一次性使用多个语言配置:
---
# We'll use defaults from the LLVM style, but with 4 columns indentation.
BasedOnStyle: LLVM
IndentWidth: 4
---
Language: Cpp
# Force pointers to the type for C++.
DerivePointerAlignment: false
PointerAlignment: Left
---
Language: JavaScript
# Use 100 columns for JS.
ColumnLimit: 100
---
Language: Proto
# Don't format .proto files.
DisableFormat: true
---
Language: CSharp
# Use 100 columns for C#.
ColumnLimit: 100
...
也可以在源码里面进行特殊注释,来表明哪一段代码不需要格式化。
int formatted_code;
// clang-format off
void unformatted_code ;
// clang-format on
void formatted_code_again;
// clang-format off
和// clang-format on
自身会被格式化。
1.2 下载Clang-tools
Clang-tool是LLVM环境自带的工具集,其除了Clang-format格式化工具外,还有代码检查工具,如Clang-tidy,Clang-check等。
Clang-tool可以被集成在Vim、Emacs、VS code、Git等中,详情参考官方文档:
Clang-format也可以源码的形式集成在应用中。
下载有多种方式,最新版本需要在LLVM下载界面进行下载,其被包含在LLVM环境中:
比如Windows下载:
由于这些下载在github上,因此下载速度有限,可通过浏览器插件安装github下载加速插件,或者使用代理进行下载。
安装之后,clang-format即在安装根目录之下:
将该目录加进PATH
环境变量中即可(安装时有这个选项,也可以手动添加)。
此外,诸如VScode,其C/C++扩展插件自带一个捆绑的clang-format和clang-tidy,但是版本可能并不是最新的。
在Linux下,也可以之间通过包管理器来安装:
sudo apt install clang-format
注意,该版本同样大概率不是最新的,因此一些特性是无法使用的。
2. 配置字段解释
2.1 language 编程语言
# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto
Language: Cpp
可以指定当前配置文件为了哪些文件配置的。
2.2 BaseOnStyle 基础风格
BasedOnStyle: LLVM|Google|Chromium|Mozilla|WebKit|Microsoft|GNU
指定基本的风格样式,实际开发时无需从头开始指定所有的格式。
2.3 AccessModifierOffset 访问性修饰符偏移
# 访问说明符(public、private等)的偏移(缩进或者对齐)
AccessModifierOffset: -4
这个是相对于原来已有的缩进而言:
template <typename type> //模板定义
// template <class type> 较老的实现
class stack //定义一个模板类
{
private: //私有是默认属性,可省略
//类声明中无法给没有分配空间的变量赋值(只是一起声明了一类变量)
//某些常量或者静态常量变量(含有存储空间)则可以初始化
int var;
}
原来的缩进是4个空白字符,这个表明在原来缩进4个字符的情况下偏移量,即回退4个字符,那相当于不缩进了。
2.4 AlignAfterOpenBracket 开括号后的对齐
# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行)
AlignAfterOpenBracket: Align
-
Align
,在开括号之后对齐变量someLongFunction(argument1, argument2);
-
DontAlign
, 不对齐,换行后使用ContinuationIndentWidth
。someLongFunction(argument1, argument2);
-
AlwaysBreak
,一行放不下时,总是在一个开括号之后换行。someLongFunction( argument1, argument2);
-
BlockIndext
,一行放不下时,总是在一个开括号之后换行,且在新行关闭尾括号。仅限于圆括号。someLongFunction( argument1, argument2 )
2.5 AlignArrayOfStructures 对齐结构体数组
当数组的列数相等时,会对齐每行的文本。
Left
,左对齐列:
struct test demo[] =
{
{56, 23, "hello"},
{-1, 93463, "world"},
{7, 5, "!!" }
};
Right
,右对齐列:
struct test demo[] =
{
{56, 23, "hello"},
{-1, 93463, "world"},
{ 7, 5, "!!"}
};
使用None
表示不用对齐。
2.6 AlignConsecutiveAssignments 对齐连续赋值
# 连续赋值时,对齐所有等号
AlignConsecutiveAssignments: true
下面的格式是连续赋值:
int a = 1;
int somelongname = 2;
double c = 3;
该选项有两种生效方法,低版本只支持指定固定的模式,如下面其中一种:
#配置一个参数:None - Consecutive - AcrossEmptyLines - AcrossComments - AcrossEmptyLinesAndComments
AlignConsecutiveAssignments: AcrossEmptyLinesAndComments
最新版本支持分别指定属性,包括额外对混合元素符(+=等)的支持:
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: true
PadOperators: true
bool Enabled: true
默认的连续赋值对齐在以下的情况下生效:
int a = 1;
int somelongname = 2;
double c = 3;
int aaaa : 1;
int b : 12;
int ccc : 8;
int aaaa = 12;
float b = 23;
std::string ccc;
bool AcrossEmptyLines
可以跨越空白行进行对齐
true:
int a = 1;
int somelongname = 2;
double c = 3;
int d = 3;
false:
int a = 1;
int somelongname = 2;
double c = 3;
int d = 3;
bool AcrossComments
可以跨越注释行进行对齐
true:
int d = 3;
/* A comment. */
double e = 4;
false:
int d = 3;
/* A comment. */
double e = 4;
bool AlignCompound
混合运算符+=
会对齐于=
(仅限于连续赋值)
true:
a &= 2;
bbb = 2;
false:
a &= 2;
bbb = 2;
bool PadOperators
混合运算符填补对齐到所有左值的最右边边界。(仅限于连续赋值)
true:
a >>= 2;
bbb = 2;
a = 2;
bbb >>= 2;
false:
a >>= 2;
bbb = 2;
a = 2;
bbb >>= 2;
2.7 AlignConsecutiveBitFields 位段对齐
主要用于结构体位段的对齐,如下:
struct aa {
int test : 4;
int b : 5;
int c : 8;
};
其支持以下属性:
None - Consecutive - AcrossEmptyLines - AcrossComments - AcrossEmptyLinesAndComments
其设置方法和属性与AlignConsecutiveAssignments
一致。
AlignConsecutiveBitFields: AcrossEmptyLinesAndComments
#或者
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
2.8 AlignConsecutiveDeclarations 连续声明对齐
可以对齐变量等连续声明的语句。
int aaaa = 12;
float b = 23;
std::string ccc;
const char hexdigits[] = "0123456789abcdef";
void Ipv6_deal(const uint16_t *a);
int main(const uint16_t *a, const uint16_t *k) { ... }
需要注意,这个方法配置最好不要跨过空白行,因为容易把函数定义也给对齐了。
其支持以下属性:
None - Consecutive - AcrossEmptyLines - AcrossComments - AcrossEmptyLinesAndComments
其设置方法和属性与AlignConsecutiveAssignments
一致。
AlignConsecutiveDeclarations: AcrossComments
#或者
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
2.9 AlignConsecutiveMacros 连续宏定义对齐
#define SHORT_NAME 42
#define LONGER_NAME 0x007f
#define EVEN_LONGER_NAME (2)
#define foo(x) (x * x)
#define bar(y, z) (y + z)
需要注意,这个方法配置最好不要跨过空白行,因为空白行可以用来做段分割符。
其支持以下属性:
None - Consecutive - AcrossEmptyLines - AcrossComments - AcrossEmptyL