clang-format 中有很多 SpaceXxx,可自行查看官网说明。

1. 单行注释前的空格(SpacesBeforeTrailingComments)

行尾注释符号(//)之前,空格的数目,默认为 2

  • 效果一
// SpacesBeforeTrailingComments: 2
// AlignTrailingComments: true

int    x   = 1;    // 为 x 赋值
float  yy  = 2.0;  // 为 yy 赋值
double zzz = 3.0;  // 为 zzz 赋值
  • 效果二
// SpacesBeforeTrailingComments: 4
// AlignTrailingComments: true

int    x   = 1;      // 为 x 赋值
float  yy  = 2.0;    // 为 yy 赋值
double zzz = 3.0;    // 为 zzz 赋值

2. 小括号内的空格(SpacesInParens)

控制是否在 ( 后和 ) 前插入空格,有两个常用值:

  • Never:不在括号内加空格
  • Custom:使用子选项精细控制

当设置为 Custom 时,SpacesInParensOptions 下的子选项(布尔值)会逐项生效,控制哪些场景下在 ( 后和 ) 前插入空格

  • 效果演示(着重看 Other 和 ExceptDoubleParentheses 组合的情况)
#include <cstdint>
#include <iostream>

// 简单函数,用于示例
int  foo(int x, int y) { return x + y; }
void h( ) {}    // 空括号示例(InEmptyParentheses 生效时会显示为 "h( )")
void g( ) { std::cout << "g\n"; }

int  main( ) {
  int a = 1;
  int b = 0;

  // 条件语句内括号空格示例
  if ( a == b ) {
    g( );
  } else {
    std::cout << "not equal\n";
  }

  // C 风格强制转换示例(InCStyleCasts 控制是否在括号内加空格)
  long    y      = 42;
  int32_t x      = ( int32_t )y;

  // 函数调用括号示例
  int     result = foo(a, b);

  // 双重括号示例(ExceptDoubleParentheses 控制)
  // 当 Other=true,ExceptDoubleParentheses=false  时,以下代码会变为 "ok = ( (a = b) );"
  // 当 Other=true,ExceptDoubleParentheses=true   时,以下代码会变为 "ok = (( a = b ));"
  // 当 Other=false,ExceptDoubleParentheses=true  时,以下代码会变为 "ok = ((a = b));"
  // 当 Other=false,ExceptDoubleParentheses=false 时,以下代码会变为 "ok = ((a = b));"
  // 注意:只有当左右括号成对包裹同一表达式(如 ((a=b)) 或 if ((a=b)))时,ExceptDoubleParentheses 才会生效
  bool    ok     = ((a = b));

  // 循环条件括号示例
  for ( int i = 0; i < 3; ++i ) {
    if ( i % 2 == 0 ) {
      std::cout << i << '\n';
    }
  }

  // 调用带“空括号内空格”的函数
  h( );

  return 0;
}

3. 小括号前的空格(SpaceBeforeParens)

用来控制是否在某些情况下在 ( 前插入空格,比如 if (, f (),有以下常用枚举值:

Never:                                  # 尽量不加空格。
ControlStatements:                      # 仅在控制语句关键字后(if/for/while/switch)加空格。
ControlStatementsExceptControlMacros:   # 同上,但对某些宏(如 FOR_EACH)不应用。
NonEmptyParentheses:                    # 仅当括号内部非空时才加空格(f( ) 不加,f( x ) 加)。
Always:                                 # 尽量在所有可放置空格的位置加空格(受语法限制)。
Custom:                                 # 使用 SpaceBeforeParensOptions 逐项精细控制(推荐)。

SpaceBeforeParensOptionsCustom 模式下的子选项,可以设置这些布尔子选项来精确控制,如下:

# 控制语句关键字后(if/for/while/switch)是否有空格。
# 例:if (cond) vs if(cond)
AfterControlStatements: true|false

# 函数声明名与 ( 之间是否有空格
# 例:void f (); vs void f();
AfterFunctionDeclarationName: true|false

# 函数定义名与 ( 之间是否有空格。
# 例:void f () {} vs void f() {}
AfterFunctionDefinitionName: true|false

# not 关键字后是否有空格。
# 例:return not (a || b); vs return not(a || b);
AfterNot: true|false

# 重载运算符后是否有空格。
# 例:void operator++ (int); vs void operator++(int);
AfterOverloadedOperator: true|false

注意:各选项互相叠加、且受语法规则限制(例如宏名是否识别为控制宏)

  • 效果演示
// 以上5个子选项都设置为 true

#include <concepts>
#include <iostream>
#include <vector>

// 示例函数与声明 / 定义 的差异
void declaration_example ( );                             // If `AfterFunctionDeclarationName: true` -> `void declaration_example ();`
void declaration_example ( ) { std::cout << "def\n"; }    // If `AfterFunctionDefinitionName: true` -> `void declaration_example () {`

// 重载运算符示例
struct S {
  // If `AfterOverloadedOperator: true`  -> `void operator++ (int) { ... }`
  void operator++ (int) { std::cout << "post++\n"; }
};

int main ( ) {
  // 控制语句:if/for/while 的空格由 AfterControlStatements 控制
  int a = 1;
  int b = 2;
  if ( a == b ) {    // space: "if( a == b )" vs "if ( a == b )"
    std::cout << "equal\n";
  } else {
    std::cout << "not equal\n";
  }

  std::vector<int> v = {1, 2, 3};
  for ( auto item : v ) {    // space: "for( auto item : v )" vs "for ( auto item : v )"
    std::cout << item << "\n";
  }

  // not 操作符示例(AfterNot 控制)
  bool flag = not (a > b);    // `not (a>b)` vs `not(a>b)`

  // 调用函数时,SpaceBeforeParens 通常不影响函数调用本身(多为函数声明/定义与控制语句)
  declaration_example( );

  return 0;
}

4. 中括号内/前的空格

# 是否在 [ 与 ] 内部插入空格,例如 a[ 5 ] vs a[5]
# 适用场景:数组声明、索引表达式等(lambda 的 [] 不受影响)
SpacesInSquareBrackets: true|false

# 是否在标识符和第一个 [ 之间插入空格,例如 int a [5]; vs int a[5];)
# 对于多维数组只对 “第一个 [” 生效(比如 int multi [2][3]; 后续 [ 不再额外加空格)
SpaceBeforeSquareBrackets: true|false
  • 效果一
// SpacesInSquareBrackets: false
// SpaceBeforeSquareBrackets: false

#include <iostream>
#include <vector>

int main ( ) {
  // 1) Simple C-style arrays (declaration and indexing)
  int a[5]    = {0, 1, 2, 3, 4};           // declaration: `int a[5];`
  int b[2][3] = {{1, 2, 3}, {4, 5, 6}};    // multi-dimensional array

  std::cout << "a[0] = " << a[0] << "\n";
  std::cout << "b[1][2] = " << b[1][2] << "\n";

  // 2) std::vector indexing
  std::vector<int> v = {10, 11, 12};
  std::cout << "v[1] = " << v[1] << "\n";

  return 0;
}
  • 效果二
// SpacesInSquareBrackets: true
// SpaceBeforeSquareBrackets: true

#include <iostream>
#include <vector>

int main ( ) {
  // 1) Simple C-style arrays (declaration and indexing)
  int a [ 5 ]      = {0, 1, 2, 3, 4};           // declaration: `int a[5];`
  int b [ 2 ][ 3 ] = {{1, 2, 3}, {4, 5, 6}};    // multi-dimensional array

  std::cout << "a[0] = " << a [ 0 ] << "\n";
  std::cout << "b[1][2] = " << b [ 1 ][ 2 ] << "\n";

  // 2) std::vector indexing
  std::vector<int> v = {10, 11, 12};
  std::cout << "v[1] = " << v [ 1 ] << "\n";

  return 0;
}

5. 尖括号内的空格(SpacesInAngles)

它决定在 <> 符号内部是否添加空格,有以下常用枚举值:

  • Never:默认值,在尖括号内不添加空格

  • Always:在尖括号内总是添加空格

  • Leave:保留原有的空格格式(不修改)

通常使用默认值 Never

  • 效果一
// SpacesInAngles: false

#include <iostream>
#include <map>
#include <string>
#include <vector>

// 模板函数示例
template <typename T>
T add (T a, T b) {
  return a + b;
}

int main ( ) {
  // 1. 简单模板实例化
  std::vector<int>           numbers   = {1, 2, 3, 4, 5};
  std::map<std::string, int> wordCount = {{"hello", 3}, {"world", 5}};

  // 2. 模板函数调用
  int sum = add(10, 20);
  std::cout << "Sum: " << sum << std::endl;

  double doubleSum = add(3.14, 2.71);
  std::cout << "Double sum: " << doubleSum << std::endl;

  return 0;
}
  • 效果二
// SpacesInAngles: true

#include <iostream>
#include <map>
#include <string>
#include <vector>

// 模板函数示例
template < typename T >
T add (T a, T b) {
  return a + b;
}

int main ( ) {
  // 1. 简单模板实例化
  std::vector< int >           numbers   = {1, 2, 3, 4, 5};
  std::map< std::string, int > wordCount = {{"hello", 3}, {"world", 5}};

  // 2. 模板函数调用
  int sum = add(10, 20);
  std::cout << "Sum: " << sum << std::endl;

  double doubleSum = add(3.14, 2.71);
  std::cout << "Double sum: " << doubleSum << std::endl;

  return 0;
}

6. 其他空格选项(9个)

# 在逻辑非运算符 ! 后是否插入空格。
# true:  if ( ! flag )
# false: if ( !flag )
SpaceAfterLogicalNot: true|false

# 在 operator 关键字与紧随的符号之间是否有空格(影响运算符重载声明/定义的外观)。
# true:  bool operator == (int) const; vs 
# false: bool operator== (int) const;
SpaceAfterOperatorKeyword: true|false

# 在 C 风格强制转换后的类型括号后是否插空格。
# true:  x = ( int ) y;
# false: x = ( int )y;
SpaceAfterCStyleCast: true|false

# 在 case 标签的 : 前是否插入空格。
# true:  case 1 :
# false: case 1:
SpaceBeforeCaseColon: true|false

# 控制空花括号 {} 内是否留空格(作用于函数体、类、lambda、初始化等)。
# Always: void f() { }
# Block: 仅空块保留空格
# Never: void f() {}
# 注意:这个在 clang-format 22 版本中引入的,我们现在用的版本是 21.1.8。这里不演示了
SpaceInEmptyBraces: SpaceInEmptyBracesStyle

# 设定 // 行尾注释与代码之间的最少空格数(例如 2 则 expr;  // comment)。
SpacesBeforeTrailingComments: Unsigned

# 是否在赋值符号 = 左侧强制有空格。
# true:  a = 1;
# false: a= 1;
SpaceBeforeAssignmentOperators: true|false

# 范围 for 的冒号 : 前是否有空格。
# true:  for (auto v : vec)
# false: for(auto v: vec)
SpaceBeforeRangeBasedForLoopColon: true|false

# 在继承列表的冒号 : 前是否加空格。
# true:  class D : B {}
# false: class D: B {}
SpaceBeforeInheritanceColon: true|false
  • 效果演示
#include <iostream>
#include <map>
#include <string>
#include <vector>

// SpaceBeforeInheritanceColon
struct Base {};
struct Derived: Base {};

// SpaceInEmptyBraces (Always / Never)
// Always: "void f() { }"  Never: "void f() {}"
void emptyBraces () {}

// SpaceAfterOperatorKeyword
struct Op {
    bool operator == (int) const { return true; }
};

// SpaceAfterCStyleCast
double d              = 3.14;
int    fromCStyleCast = ( int )d;

// SpaceAfterLogicalNot
void test_logical_not (bool flag) {
    if ( !flag ) {
        std::cout << "flag is false\n";
    } else {
        std::cout << "flag is true\n";
    }
}

// SpacesBeforeTrailingComments demonstration
int x1 = 1;    // comment

// SpaceBeforeAssignmentOperators
int x2 = 10;

// SpaceBeforeRangeBasedForLoopColon
void test_range_for () {
    // 定义一个vector
    std::vector<int> vec = {4, 5, 6};
    for ( auto v : vec ) {
        std::cout << v << ' ';
    }
    std::cout << '\n';
}

// SpaceBeforeCaseColon
int switch_demo (int n) {
    switch ( n ) {
        case 1:
            return 10;
        case 2:
            return 20;
        default:
            return 0;
    }
}

int main () {
    std::cout << "Derived types exist: " << sizeof(Derived) << "\n";
    test_logical_not(false);
    test_range_for();

    std::cout << "switch_demo(1) = " << switch_demo(1) << "\n";

    return 0;
}