编码规范
本文档介绍 ReactOS 新增代码需遵循的通用编码规范,仅适用于 C 和 C++ 源代码文件。本规范由 ReactOS 团队在 2013 年 10 月会议上正式敲定。
除非存在特殊原因(例如代码近期会彻底重写),现有历史代码应尽量按照本规范统一格式。详情参见现有代码格式调整说明。
与其他项目(如 Wine)同步的代码禁止修改格式 。可通过以下文件查看同步文件清单:第三方文件说明、Wine 同步文件说明。
文件结构
- 所有 ReactOS 源代码文件必须添加如下文件头注释:
c
运行
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Does cool things like Memory Management
* COPYRIGHT: Copyright 2017 Arno Nymous <abc@mailaddress.com>
* Copyright 2017 Mike Blablabla <mike@blabla.com>
*/
请使用 SPDX 许可证标识,便于授权检测工具解析代码文件。
若你对文件做出重大贡献、能够全权负责该文件整体或部分代码,可将姓名添加至COPYRIGHT版权区域。单个文件版权署名人数不得超过 3 人 。 旧版文件头中的FILE字段需全部移除。
缩进与行宽
- 代码单行字符数最大限制为 100 个。
- 代码行末尾禁止添加空格或制表符。
- 统一使用4 个空格缩进,禁止使用制表符(Tab)。
switch语句中,case标签与对应代码均需缩进。
正确示例:
c
运行
switch (Condition)
{
case 1:
DoSomething();
break;
case 2:
{
DoMany();
ManyMore();
OtherThings();
break;
}
}
错误示例:
c
运行
switch(Condition)
{
case 1:
DoSomething();
break;
case 2:
DoMany();
ManyMore();
OtherThings();
break;
}
- 函数调用若一行无法容纳,参数按如下方式对齐:
c
运行
FunctionCall(arg1,
arg2,
arg3);
- 函数声明需遵循以下格式(严格保持示例中的字段顺序):
c
运行
static // 作用域标识
CODE_SEG("PAGE") // 代码段设置
// 其他属性
BOOLEAN // 返回值类型
FASTCALL // 调用约定
IsOdd(
_In_ UINT32 Number);
空格使用规范
-
一元运算符 两侧不加空格。 正确:
i++;错误:i ++; -
二元运算符、三目运算符 两侧必须添加空格。 正确:
a = b + c;错误:a=b+c; -
逗号、分号前方禁止添加空格。
正确示例:
c
运行
for (int i = 0; i < 5; i++)
DoSomething();
func1(a, b);
错误示例:
c
运行
for (int i = 0; i < 5 ; i++)
DoSomething();
func1(a , b) ;
- 流程控制关键字与括号之间添加空格。
正确:
c
运行
if (Condition)
DoSomething();
错误:
c
运行
if(Condition)
DoSomething();
- 函数名与括号、括号与内部参数之间禁止添加空格。
正确:
c
运行
func(a, b);
错误:
c
运行
func (a, b);
func( a, b );
代码换行
- 每条语句独占一行。
正确示例:
c
运行
x++;
y++;
if (Condition)
DoSomething();
错误示例:
c
运行
x++; y++;
if (Condition) DoSomething();
大括号规则
- 左大括号
{和右大括号}必须单独成行。 - 单行逻辑的控制语句可省略大括号,不作强制要求;若单行语句附带注释,则必须添加大括号。
正确示例:
c
运行
if (Condition)
DoSomething();
if (Condition)
{
DoSomething();
}
if (Condition)
{
// 此处添加注释
DoSomething();
}
if (A_Very || (Very && Long || Condition) &&
On_Many && Lines)
{
DoSomething();
}
if (Condition)
DoSomething();
else
DoSomethingElse();
if (Condition)
{
DoSomething();
}
else
{
DoSomethingElse();
YetAnother();
}
错误示例:
c
运行
if (Condition) {
DoSomething();
}
if (Condition)
// 此处添加注释
DoSomething();
if (A_Very || (Very && Long || Condition) &&
On_Many && Lines)
DoSomething();
if (Condition)
DoSomething();
else {
DoSomethingElse();
YetAnother();
}
流程控制结构
-
条件判断禁止使用逆序判断写法 。 正确:
if (i == 1)错误:if (1 == i) -
避免多层嵌套的分支结构,优先使用线性代码风格,而非树形嵌套风格。为简化代码(如统一资源释放逻辑),可合理使用
goto语句。
正确示例:
c
运行
if (!func1())
return;
i = func2();
if (i == 0)
return;
j = func3();
if (j == 1)
return;
...
错误示例:
c
运行
if (func1())
{
i = func2();
if (func2())
{
j = func3();
if (func3())
{
...
}
}
}
命名规则
- 变量、函数名首字母大写 。开发 Win32 相关代码可使用匈牙利命名法,不作强制要求;即便不使用匈牙利命名法,名称首字母也必须大写,禁止使用小驼峰命名法,名称中也不得使用下划线作为分隔符。
正确示例:
c
运行
PLIST_ENTRY FirstEntry;
VOID NTAPI IopDeleteIoCompletion(PVOID ObjectBody);
PWSTR pwszTest;
错误示例:
c
运行
PLIST_ENTRY first_entry;
VOID NTAPI iop_delete_io_completion(PVOID objectBody);
PWSTR pwsztest;
- 函数、变量名称尽量完整,避免随意缩写,语义需清晰易懂。
- 布尔类型变量命名,建议搭配
is、did等动词前缀,提升可读性。
正确:
c
运行
BOOLEAN IsValid;
BOOLEAN DidSendData;
错误:
c
运行
BOOLEAN Valid;
BOOLEAN SentData;
注释规范
- 单行内容不要拆分为多行注释,避免冗余空行。
正确示例:
c
运行
// 这是单行注释
/* 标准 C 风格注释 */
// 这是多行注释
// 多行注释无强制格式要求
错误示例:
c
运行
//
// 多余空行,浪费代码行数
//
空指针、布尔值与数值 0
- 空指针统一使用
NULL;仅在特殊环境下(如 C++11)可使用nullptr,禁止直接使用数字 0 表示空指针。 - Win32/NT 体系布尔值使用
TRUE和FALSE;若使用标准 C/C++bool类型变量,则使用true和false。 - 判定或终止 ANSI/OEM 字符串时,使用
ANSI_NULL;判定或终止 Unicode 宽字符串时,使用UNICODE_NULL。
现有代码格式调整说明
- 禁止在同一次提交中,既修改代码逻辑又统一代码格式,两类变更需拆分不同提交记录。
- 若某次提交仅为格式调整,提交说明开头必须标注
[FORMATTING]。
其他规范
- 若非调用接口必需,禁止使用
LARGE_INTEGER/ULARGE_INTEGER,统一改用INT64/UINT64。 - 头文件防护统一使用
#pragma once,不再使用宏守卫写法。 - 除非接口、导出符号有强制要求,否则函数无需显式指定调用约定。
自动代码格式化工具
待补充(编辑者:Zefklop)
暂未制定规则的内容
文档讨论阶段曾提出部分补充建议,但未达成团队共识,因此暂不作强制规范: 待补充(编辑者:Hbelusca)