• 抬起头,继续前进吧,去把这个不完美的故事,变成你成所期望的样子
  • 登山路上我们会放弃很多东西,但这些被我们丢掉在我们登上山顶之际,都会一一回来
  • 不论开发还是逆向,数学水平的高低直接决定了”你的饭碗里有没有肉”
  • 万丈高楼平地起,勿在浮沙筑高台

【个人向】Windows平台C/C++代码风格规范

C 菜鸟 1年前 (2018-05-14) 20249次浏览 已收录 0个评论
[隐藏]

前言

        菜鸟好几天没有更新博客了,是因为文章其实已经写好了,只是事情比较多还没来得及排版….
        关于 C 语言的学习,菜鸟一直使用的是 Linux 环境,由于一些原因准备向 Windows 转。同时也发现了之前的编码风格很随性,没有准确的规范。写代码需要的自由,是完全的规范框架下的自由~今天就在这篇文章中明确写明一些个人编码规范,目前只整理了部分,以后还会不断完善更新。
        其实没有最好的规范,只要自己能坚持就好啦。当然在项目中还是以整个项目风格规范为最优先~而且如果是修改别人的代码,也要优先遵循原作者的代码风格~

1. 基础规范

主要描述一些统一化的东西。

1.1. 行宽统一

一行统一 80 个字符为最大值。

1.2. 制表符统一

1 个制表符转换为 4 个空格。

2. 头文件

主要描述头文件的规范。

2.1. 头保护

每个头文件中要进行头保护操作
格式如下:

#ifndef 保护宏
#define 保护宏
....
#endif //!保护宏

保护宏命名格式为 头文件名称 _H_
例如:BOOLENV_H_

2.2 头文件包含次序

1. 某些需要特别优先的特殊头文件
2. C 语言系统库文件
3. C++语言系统库文件
4. 其他库文件
5. 本项目内头文件

3. 注释

统一注释风格://(特别情况会另行说明)

3.2 函数声明注释

信息如下:
1. 函数功能介绍
2. 是否有信息显示输出
3. 返回值说明
4. 参数说明..
5. 使用注意事项
示例:

//**********************************************************************
// FUNCTION:     Insert client infomation to m_mapClient
// OUPUT:        None
// RETURN:       Successful (TRUE) or failure (FALSE)
// PARAMETER:
//      sctTargetSocket:    A socket which take to bind, is Key in map
//      pClientInfo:        A ClientInfo point which bind with socket,
//                          is value in map
// NOTE:        
//      1. Point cann't be NULL.
//**********************************************************************

int DeleteString(…);

3.3 函数定义注释

主要对函数实现过程进行说明
示例:

//******************************************************************************
// Author:              Hoffman
// Create Time:         2019-01-09
// Last Time:           2019-01-09
// Logical Description:  
//      
//******************************************************************************
void FlushStorageResource_c(char acStorageResource[],
                            char acStorageRegion[])
{
…
}

3.4 变量注释

如果变量过多,需要标注变量是哪个功能所涉及的,与下一个变量注释区域用空行分隔
示例:

//存储区域
char acStorageRegion[STORAGE_SIZE] = { 0 };

//涉及添加字符串的数据
char szInputAddString[INPUT_SIZE] = { 0 };

3.5 特别注释

1. 如果一些代码可读性不是很好,可以特别进行注释说明
2. 可以在代码块尾的左大括号进行如下注释(不强制)。但要求函数定义尾必须使用该注释
格式://! 标识 END
示例:

// 注释信息
for(;;)
{
    …
} //! for '注释信息' END

4. 命名

在命名时在名称不是过长的情况下,尽量不要使用缩写且力求意思完整。
如果要使用缩写,请使用通用缩写表内的缩写。

4.1 变量(对象)

使用匈牙利命名法前缀,满足小驼峰格式,变量名要尽量将含义表示出来。
例如:类的 int 型成员变量 m_iScore
如果是类类型声明的对象,则首字母大写,例如:std::strng Name;

首部 含义 衍生 含义
g_ 全局变量 g_ 子类型 某类型的全局变量
m_ 成员变量 m_ 子类型 某类型的机构成员
ref_ 引用
flt 单精度浮点型
dbl 双精度浮点型
i 整型
p 指针 pc (注 1) 字符型指针
psz 保存字符串的首地址
pfn 函数指针
pa[type] [type]数组指针
pi 整型指针
pst 结构指针
pfile 文件指针
pfn 函数指针
a 数组 ai 整型数组
ac 字符型数组
ad 双精度浮点型数组
af 单精度浮点型数组
ap[子类型] 某类型指针数组
ast 结构数组
c 字符
sz 按字符串格式规范的字符数组
u 无符号 ui 无符号整型
uc 无符号字符型
st 结构体
tag 标记
w
uni 联合
e 枚举
C 普通类
I 接口父类【不实例化】
k const kp 顶层 const
pk 底层 const
t 时间(time_t or clock_t)
si 短整型
l long
f 文件
by 字节
thd 进程
que 队列
vct vector
list 链表
map 哈希表
excpt 异常
*注 1* pc 用于说明该指针变量主要对单个字符进行操作,不对字符串进行操作。起说明作用。

4.2 函数

使用动词进行命名,驼峰法且首字母大写。例如:ReadCards()
特殊情况需要区分参数类型的可以使用下划线后给类型标识。
例如:针对字符型参数的函数名,FlushStorageResource_c()

4.3 自定义宏

全部字母大写,使用下划线做分隔,与函数和变量做区分。例如:NUM_CARDS

4.4 自定义类型

大驼峰法,不使用下划线分隔,例如:Bool

*注意* 指针函数类型要加 PFN_ 前缀

4.5 文件

1. main 函数所在文件命名为 Launch。
2. 自定义函数所在源文件使用小驼峰法,例如:mainActive.c。
3. c 语言源文件使用.c 后缀,c++源文件使用.cpp 后缀。
4. 头文件统一使用.h 后缀。
5. 自定义宏和自定义类型的头文件名称使用大驼峰法例如:BoolEnv.h。
6. 自定义类的头文件和类名保持一致。
7. 自定义函数的声明头文件名称使用小驼峰法,例如:mainActive.h。
8. 如果文件名中有数字,则数字和字母之间用 _ 分隔。

4.6 自定义命名空间

大驼峰法,不使用下划线分隔,例如:NampSpace

5. 格式

5.1 变量初始化

类型 初始化值
int 0
float 0.0f
char ‘\0’
double 0.0
指针类型 NULL

5.2 表达式

5.2.1 算术表达式

        1. 算术运算符左右保留 1 个空格
        2. 换行时,第二行缩进 4 个空格,优先在+/-后进行换行,然后是乘/除. 取余符号
        3. 乘/除法如果的两个操作数不在同一行,注意使用圆括号包裹,起标识说明作用

5.2.2 赋值表达式

赋值运算符左右保留 1 个空格
a. 包含算术表达式的情况
如果一行超过 80 字符
1. 从右向左查找换行后使一行小于 80 字符的位置,按照算术表达式的规则进行换行。
2. 保持换行位置赋值/算术运算符之后
3. 换行后进行 4 空格缩进

b. 不包含算术表达式的情况
如果一行超过 80 个字符,则在赋值运算符后换行,换行后的内容缩进 4 个空格

5.2.3 布尔表达式

1. 如果有含有多个运算符的表达式要进行换行,保持&&运算符在行尾,||运算符在行首。
2. 二级布尔表达式用圆括号包裹。
3. 如果是变量与一个固定值进行==或!=判断,则固定值在判断符左边,变量在判断符右边。

5.2.3 指针和引用

1. 句点(.)和箭头(->)前后不要有空格。
2. 指针/地址操作符(*. &)后不要有空格。

5.3 结构体

1. 结构体声明放在头文件中,声明格式统一使用 typedef 声明或 struct 结构标记(二选其一)
2. 结构体统一使用列表初始化方式。
3. 如果需要更改对齐值,需要限定对齐值作用范围。如下:

#pragma pack(push)
#pragma pack(n)
………
#pragma pack(push)

5.4 类型限定符

除了指针类型,类型限定符放置在类型说明符前面。

5.5 函数

5.5.1 声明与定义

1. 返回值总是和函数名在同一行。
2. 函数定义时左大括号总是单独占一行。
3. 左圆括号总是和函数名在同一行。
4. 函数名和左圆括号之间没有空格。
5. 圆括号和参数之间没有空格。
6. 右大括号总是单独位于函数最后一行。
7. 函数声明和实现处的所有形参名称必须保持一致。
8. 所有形参应尽可能对齐。
9. 函数定义时形参名与声明时的形参名保持一致。

5.5.2 调用

针对调用时超过 80 个字符的情况。
首先在逗号后换行,每个参数一行。示例如下:

bRet = m_pageSectionInfo.Create(IDD_PROPPAGE_SECTIONINFO,
                                &m_tabAbilityOption);

如果仍旧超过 80 字符,则在左圆括号后换行,参数为缩进 4 空格对齐,右圆括号与分号独占一行。示例如下:

m_listSectionInfo.InsertColumn(
    cntI,
    m_acsSectionInfoListColumnTitle[cntI],
    0,
    COLUMN_WIDTH
);

5.6 结构控制

1. 所有控制结构不能省略大括号(除了多个 case 使用同一块代码处理的情况)。
2. 空控制结构使用如下格式表示

...
{
}

5.6.1 if…else

1. 左右圆括号内部不添加空格。
2. 关键字 else 另起一行。
3. if 和左圆括号之间有空格。
4. 对于布尔类型直接进行判断而不使用==。

5.6.2 switch

1. 如果需要 break,则 break 位于大括号内。

5.6.3 for

1. 在分号后面空 1 格。
2. 如果超过 80 字符,则在分号后换行。
3. for 和左圆括号之间有空格。

5.6.5 while/do…while

1. for 和左圆括号之间有空格。
2. 对于布尔类型直接进行判断而不使用==。
3. do 单独占一行。

5.7 预处理指令

预处理指令不要缩进,直接从行首开始。

6. 异常

1. 在项目起始前要确定是否使用异常,如果使用则都要遵守异常规范
2. 如果函数没有异常抛出,则使用 noexcept 异常说明。有异常抛出的话在注释中说明
3. 除了 bad_alloc,统一使用自定义异常
4. 使用栈展开的方式来自动销毁资源
5. 函数声明和定义处都要有异常说明
6. 如果函数的异常声明过长可单独另起一行

小结

整个规范可能刚开始有些吃力,可以先强制自己遵守一部分,然后养成习惯后再继续往上加。严格一些还是好的,因为你不会知道在真正的工作项目中会有些什么要求。
那就这样啦 Happy Coding~


学习心得 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明【个人向】Windows 平台 C/C++代码风格规范
喜欢 (3)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址