讲解 clang-format的下载安装、预定义风格、规则详解

1. 下载与安装

clang-format 是一个强大的代码格式化工具,专门用于格式化 CC++Objective-CJavaJavaScriptTypeScript 等编程语言的代码。

clangLLVM 项目中的 C / C++ / Objective-C 编译器,是 Apple 资助开发,旨在替代 GCC
clang-formatclang 工具集中的一个组件,它可以根据用户定义的配置文件(如 .clang-format)或命令行参数对代码进行格式化。

官网地址:https://github.com/llvm/llvm-project/releases,下载的文件为:LLVM-21.1.8-win64.exe
安装时记得把 C:\Program Files\LLVM\bin 目录添加到系统的 Path 环境变量,以方便在任意目录执行 clang-format 命令,如下:
llvm-path

安装完成后,目录如下:
clang-dir

此时,打开命令行窗口,就可以使用 clang-format 命令了,如下:
clang-test

2. 预定义风格

2.1 有哪些预定义风格?

Clang Format 有几十上百条规则,通常不需要程序员逐一设置,因为它提供了多种预定义风格,如下:

  • LLVM
  • Google
  • Chromium
  • Mozilla
  • WebKit
  • Microsoft
  • GNU

预定义风格中,包含了对每一条规则的设置。可以直接使用预定义的风格,来格式化代码,如下:

# 默认使用 LLVM 风格
clang-format code.cpp     # 将格式化结果打印到终端,不会修改文件
clang-format -i code.cpp  # 直接修改文件

# 显示地指定风格
clang-format -style=Google code.cpp
clang-format -style=Google -i code.cpp

2.2 来吧,演练一下

首先,将以下未经格式化的代码,保存到 test.cpp 文件中:

#include <iostream> 
using    namespace std;
 
int      main() 
{


cout << "Hello, World!" << endl;
        return 0;


}

然后,分别使用不同的预定义风格格式化代码:

  • 默认的 LLVM 风格
#include <iostream>
using namespace std;

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}
  • Google 风格
#include <iostream>
using namespace std;

int main() {
  cout << "Hello, World!" << endl;
  return 0;
}
  • Mozilla 风格
#include <iostream>
using namespace std;

int
main()
{

  cout << "Hello, World!" << endl;
  return 0;
}
  • WebKit 风格
#include <iostream>
using namespace std;

int main()
{

    cout << "Hello, World!" << endl;
    return 0;
}

可见,不同预定义风格对代码格式化的效果是有区别的,比如:

  • 缩进使用 2 个还是 4 个空格
  • 函数是否允许开始处有一个空行
  • 函数的开始花括号是和函数名在一行,还是另起一行
  • 函数返回值和函数名是否在同一行

3. 自定义风格

预定义的风格中,很可能某些规则并不符合我们的要求,比如 Google 这个风格默认的缩进为 2,我习惯改成 4

那么如何自定义风格呢?
答:通常在预定义风格基础上进行修改,形成一套符合自己的风格。

3.1 如何自定义风格

首先,导出预定义的风格

格式名的取值为 llvm, google, chromium, mozilla, webkitmicrosoftGNU
导出的文件通常命名为 .clang-format_clang-format,这样才能被 clang-format 识别

clang-format -style=google -dump-config > .clang-format

然后,打开刚导出的 .clang-format 文件,根据需要进行修改

我将缩进由 2 改为了 4,将每行字符数目由 80 改为了 120,单行的函数的函数体是否和函数名在一行

# 修改前
IndentWidth:     2
ColumnLimit:     80
AllowShortFunctionsOnASingleLine: All
 
# 修改后
IndentWidth:     4
ColumnLimit:     120
AllowShortFunctionsOnASingleLine: false

最后,执行如下命令,使用自定义的 .clang-format 文件来格式化代码

-style=file,表示要使用 .clang-format 文件来格式化代码
需要将修改好的 .clang-format 文件,拷贝到要格式化的文件所在目录,或者任一父目录。因为 clang-format 程序,在格式化时会去这些目录查找 .clang-format 文件,如果未找到,则使用默认的风格。
由于我的 test.cpp 文件在 F:\code\ 目录下,因此,可以将 .clang-format 文件拷贝到了 F 盘根目录,这样在格式化时,可以被 clang-format 程序读取到。

clang-format -style=file test.cpp

以下是使用修改前和修改后的 .clang-format文件,来格式化的效果:

  • 格式化前
#include <iostream>
using namespace std;

int add(int a, int b) { return a + b; }

int main() {
  cout << "Hello, World!" << endl;
  return 0;
}
  • 格式化后
#include <iostream>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}

3.2 出问题了

此时,使用 clang-format 命令格式化时,可能出现如下问题:
clang-err

这是因为,导出的 .clang-format 文件,不是 utf-8 格式,使用 Notepad++ 将其修改为 utf-8 即可,如下:

clang-utf16 clang-utf8