日常阅读04 google代码规范

代码编写规范说明
V0.1
Date: 2020/09
 
说明:
编码规范鼓励大家遵循 Google c++ 编码规范。
鉴于 Google 编码规范内容过多,在此基础上提出部分重点信息在此文档说
明,重点部分务必遵守,对自己有严苛要求的,尽可能多的遵守 Google c++ 编码
规范 .
排版布局
排版布局应做到美观大方;
1.1 合理使用空行:
1.1.1
函数体之间用空行分隔。
1.1.2
结构 / 联合 / 枚举声明用空行分隔。
1.1.3
不同功能的代码块之间用空行分隔。
1.1.4
将功能类似的代码(如宏定义、类型定义、函数声明和全局变量)放在一
起,和其他部分用空行分隔。
1.1.5
使用空行时,一行就够了,不要连续使用多个空行,那样会让人感觉代码
空荡荡的。
1.2 合理使用空格
1.2.1 等号两边使用空格。
如: int a = 100; 深圳乐生机器人 Co., Ltd.
 
1.2.2
参数之间使用空格。
如: test(int a, int b, int c)
1.2.3
语句末的分号与前面内容不要加空格。
如: test(a, b, c);
1.2.4
其他能让代码更美观的地方。
1.3 合理使用括号
1.3.1
用括号分隔子表达式,不要只靠默认优先级来判断。
如: ( (a && b) || (c && d) )
1.3.2
用括号分隔 if/while/for 等语句的代码块,哪怕代码块只有一行。
如:
if(a > b)
{
return c;
}
1.4 合理的缩进方式
每一级都正常缩进,用 tab 缩进取代空格缩进。之前用空格缩进的目的是防
止代码因编辑器的 tab 宽度不同而变乱,现在这个担心是多余的了,代码编辑器
都支持 tab 宽度设置了(统一设置为 4 个空格)。如果代码缩进的层次太多 ( 比如
超过三层 ) ,则可能是代码设计上出了问题。( google 规范中部分 tab 宽度设置为
2 ,这里我们统一设置为 4 ,访问限定符保持和 google 规范一致,缩进为 1
如:
if(a > b)
 
{
for(int i = 0; i < 100; i++)
{
}
}
命名和注释:
命名约定
1 、总体规则:不要随意缩写,如果说 ChangeLocalValue 写作 ChgLocVal 还有情
可原的话,把 ModifyPlayerName 写作 MdfPlyNm 就太过分了,除函数名可适当
为动词外,其他命名尽量使用清晰易懂的名词;
2 、宏、枚举等使用全部大写 + 下划线;
3 、变量(含类、结构体成员变量)、文件、命名空间、存取函数 ( 指类成员变量
存取 ) 等使用全部小写 + 下划线,类成员变量以下划线结尾,全局变量以 g_ 开头;
4 、普通函数、类型(含类与结构体、枚举类型)、常量等使用大小写混合,不含
下划线;
使用这套命名约定,可以使代码具有一定程度的“自注释”功能,方便他人
阅读,也方便自己以后修改。
注释:
首先,尽可能多的遵循约定好的代码编写规范,就是最好的注释 ; 有意义的
类型名和变量名 , 要远胜过要用注释解释的含糊不清的名字 .
隐晦难懂的变量声明和定义、宏定义、常量,全局变量等,添加注释;
对外提供的函数接口、内部函数实现特殊的操作等添加注释;
参考 Google 规范添加。
从源码编写开始,避免容易犯的错误
内存泄漏:
C/C++ 中,内存管理器不会自动回收不再使用的内存,如果你忘了释放不
再使用的内存,这些内存就不能被重用了,这就造成了内存泄漏;
malloc free 应配对使用, new 要和 delete/delete[] 配对使用。重载了类的
new 操作,应该同时重载类的 delete/delete[] 操作。
内存越界访问
内存越界访问有两种,一种是读越界,即读了不属于自己的数据。如果所读
的内存地址是无效的,程序立刻就崩溃了;如果所读内存地址是有效的,在读的
时候不会马上出现问题,但是由于读到的数据是随机的,因此它会造成不可预料
的后果。另外一种是写越界,所写入的数据对别的程序来说是随机的,它会造成
不可预料的后果。
内存越界访问会造成非常严重的后果,是程序稳定性的致命威胁之一。更麻
烦的是,它出现的时机是随机的,表现出来的症状是随机的,而且造成的后果也
是随机的。
这里举两个例子:
1 ,数据访问越界,访问数组数据时,未注意数组元素的大小,导致访问越
界。
2 strcpy(str, argv[1]); 这里是否存在越界错误依赖于外部输入的数据,这样的
写法在接受正常输入的情况下可能没有问题,但只要受到一点恶意攻击
就,或者调用者不注意,就存在了越界的情况了。所以,除非你确定输
入的数据是在你的控制之内的,否则不要用 strcpy,strcat sprintf 之类的
函数,使用 strncpy strncat snprintf 代替。
遗留野指针,访问空指针
野指针指的是那些指向你已经释放掉的内存的指针。释放掉的内存会被内存
管理器重新分配,此时,野指针指向的内存已经被赋予新的意义。对野指针的访
问,无论是有意的还是无意的,都可能会带来巨大的代价,因为它造成的后果,
如同越界访问一样是不可预料的。
释放内存后应当立即把对应的指针置为空值。需要注意:如果指针是从函数
外层传入的,那么就算在函数内把指针置为空值,也不会对外层的指针造成任何
访问空指针,空指针在 C/C++ 中有特殊的地址,通常它是用来判断一个指针
的有效性。空指针一般定义为 0 。现代操作系统都会保留从 0 开始的一块内存,
一旦程序试图访问这块内存,系统就会触发一个异常信号。
返回指向临时变量的指针
大家都知道,栈里面的变量都是临时的。当前函数执行完成时,相关的临时
变量和参数就都被清除了。不能把指向这些临时变量的指针返回给调用者,因为
这样的指针指向的数据是随机的,会给程序造成不可预料的后果。
误解传值与传引用
C/C++ 中,参数默认传递方式是传值的,即在参数入栈时被复制一份。在
函数里修改这些参数,不会影响外面的调用者。因此在操作函数传递的参数时,
务必谨记这些值只是临时拷贝数据而已。
指针操作时由于概念模糊导致的错误
比如:
int *p = ….; p + 1 等于 (size_t)p + 1 吗?
事实上 p + n 等于 (size_t)p + n * sizeof(*p)
应谨记对指针的操作,跟指针指向的数据类型密切相关。
结构体赋值不当引发的错误
在初始化一个结构体时,应避免使用下面这种方式对结构体赋值:
struct s s1 = {4, “abcd”};
正确的初始化方法应该是:
struct s s1 = {.l = 4, .p = “abcd”};
引用未初始化的变量
未初始化变量的内容是随机的,使用这些数据会造成不可预料的后果,调试
这样的 bug 也是非常困难的。要防止这类 bug 出现其实非常容易,只需在声明变
 
量时记得对它进行初始化就行。另外我们也要重视编译器的警告信息,一旦发现
引用了未初始化的变量,就要立即修改过来。
试图修改常量
避免修改全局常量和常量字符串,原因在于他们是放在 .rodata 里面,
.rodata 内存页面是不能修改的。试图对他们进行修改会引发内存错误。
符号重名
无论是函数名还是变量名,如果在不同的作用域内重名,自然没有问题。但
如果两个符号的作用域有交集,如全局变量和局部变量,全局变量与全局变量之
间,重名的现象一定要坚决避免。
栈溢出
每一个操作系统平台,堆与栈的空间大小设定不一样,通常定义一些不是特
别大的临时变量都不会有问题,如果要定义大的临时变量,应考虑栈溢出的错误,
采取必要措施避免栈溢出的可能;
误用 sizeof
尽管 C/C++ 通常是按值传递参数,但数组是个例外,在传递数组参数时,数
组退化为指针 ( 即按引用传递 ) ,此时用 sizeof 是无法获取数据的大小的。
如:
void test(char str[20])
{
printf(“%s:size=%d\n”, __func__, sizeof(str));
}
int main(int argc, char* argv[])
{
char str[20] = {0};
test(str);
printf(“%s:size=%d\n”,__func__, sizeof(str)); 深圳乐生机器人 Co., Ltd.
 
return 0;
}
字节对齐
字节对齐主要目的是提高内存访问的效率。但在有的平台 ( ARM7) 上,就不
光是效率问题了,如果不对齐,得到的数据都是错误的。
所幸的是,大多数情况下,编译器会保证全局变量和临时变量都能按正确的
方式对齐。内存管理器会保证动态内存按正确的方式对齐。要注意的是,在不同
类型的变量之间进行转换时一定要小心,如把 char * 强制转换为 int * 时,要格外
小心。
另外,字节对齐也会造成结构体大小的变化,如果是在程序内部,用 sizeof
来取得结构的大小就足够了。若数据要在不同的机器间传递时,就需要在通信协
议中规定对齐的方式,以避免对齐方式不一致引发的问题。
字节顺序
字节顺序历来是设计跨平台软件时头疼的问题。字节顺序是关于数据在物理
内存中的布局问题,最常见的字节顺序有两种:大端模式与小端模式。
在开发与网络通信和数据交换有关的软件时,要特别注意字节顺序问题。
多线程共享变量没有用 valotile 修饰
关键字 valotile 的作用时告诉编译器,不要把变量优化到寄存器里。在开发
多线程并发的软件时,如果这些线程共享一些全局变量,这些全局变量最好用
valotile 修饰。这样可以避免因为编译器优化而引起的错误 ( 往往这样的错误非常
难查 )
遵循编程思想
高内聚( High Cohesion
高内聚是一个普遍用来评判软件设计质量的标准。内聚,更为专业的说法叫功能内聚,是对
软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责
 
内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。高内聚
要求软件系统中的各个元素具有较高的协作性,因为在我们在完成软件需求中的一个功能,
可能需要做各种事情,但是具有高内聚性的一个元素,只完成它职责内的事情,而把那些不
在它职责内的事情拿去请求别人来完成。
低耦合( Low Coupling
耦合是对某元素与其它元素之间的连接、感知和依赖的量度。这里所说的元素,即可以是功
能、对象(类),也可以指系统、子系统、模块。假如一个元素 A 去连接元素 B ,或者通过
自己的方法可以感知 B ,或者当 B 不存在的时候就不能正常工作,那么就说元素 A 与元素 B
耦合。耦合带来的问题是,当元素 B 发生变更或不存在时,都将影响元素 A 的正常工作,
影响系统的可维护性和易变更性。同时元素 A 只能工作于元素 B 存在的环境中,这也降低
了元素 A 的可复用性。正因为耦合的种种弊端,我们在软件设计的时候努力追求 低耦合
低耦合就是要求在我们的软件系统中,某元素不要过度依赖于其它元素。
在实际的软件开发过程中,我们不应过度的追求高内聚、低耦合,强内聚和
弱耦合是相辅相成的,一个良好的设计是由若干个强内聚模块以弱耦合的方式组
装起来的。除了高内聚低耦合的原则,我们在开发过程中应该对可读性、复用性、
可维护性和易变更性方面投入更多的思考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幽风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值