编码规范
本文档介绍 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字段需全部移除。
- ReactOS 代码库使用 Doxygen 生成文档,函数头部需遵循标准注释格式,详见接口文档规范。
缩进与行宽
- 代码单行字符数最大限制为 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)
相关参考
- 内核编码规范
- GNU 缩进工具