文章目录
- 一、相关知识补充
- 二、规范事项
- 1、杂项
- 2、循环语句的效率
- 3、if语句
- 4、switch语句
- (1).switch语句独占一行
- (2).每个case独占一行,执行语句不得紧跟其后
- (3).若某个case没有break需要给出确认性注释
- (4).一定要有default语句
- (5).真假两种处理不应采用switch语句,应采用if语句
- (6).case语句的先后顺序要使得执行次数尽可能少
- 5、for语句
- (1).for语句独占一行,执行语句不得紧跟其后
- (2).无论有多少条执行语句,都必须用大括号将执行语句括起来
- (3).空的循环体要给出确认性注释
- (4).循环计数尽量从0开始,不要从1开始。
- (5).不要在循环体内强制变更循环变量
- (6).for循环中禁用逗号运算符
- (7).尽量避免在循环内申请/释放内存
- 6、while语句
- 7、return语句
- 8、初始化
- 9、代码格式
- (1).函数的参数一般不要超过7个
- (2).函数的大小不要过长,一般定为350行以内(去除注释、变量定义、调试开关)
- (3).嵌套语句需要4字符的缩进
- (4).用空行将代码逻辑片段进行划分
- (5).存储类型应该紧跟类型,而不是变量
- (6).在声明和定义处,将指针、引用[*, &]紧跟类型,而不是变量
- 10.函数
- (1).数组作为函数参数时,不需要指定数组大小
- (2).内定数据类型作为参数时,如果不需要修改就作为值传递而不是引用传递
- (3).使用标准库<ctype.h>或<cctype>里的函数进行字符判断
- (4).函数的声明和定义里参数标识应该保持一致
- (5).禁止函数返回局部变量的指针或引用
一、相关知识补充
1、switch接受的参数类型
switch接受的参数实际上是整型int,但是许多其他类型都可以被隐式转换为整型,所以这一点不是很明显。
2、内存分区与数据存放
如下图所示:
上述内存分区中,栈区的大小往往比堆区小很多,因此不宜在栈区申请过大的数组等。
当一个指针在堆区动态申请到一些空间时,相当与获得了堆区内存的访问权限,因此没有被申请的空间是无法访问的。
- 如果指针指向一个未被申请/已被释放的地址,则无权限访问,称为指针悬挂,这样的指针称为野指针
- 如果指针之前申请的空间未被收回,又更换了指向,则之前申请的内存将无法被别人访问,称为内存泄漏
3、变量的作用域与生命期
局部变量的作用域在代码块内,生命期持续到代码块调用结束。
全局变量的作用域是整个程序,生命期持续到程序执行结束。
堆区变量的生命期从申请内存空间开始,持续到释放内存空间结束。
4、调试开关的使用
调试开关主要通过#if
、#ifdef
、#ifndef
等预编译指令来实现。
二、规范事项
1、杂项
(1).for循环语句中只出现影响循环控制的变量
像下面这段代码中,num即为无关变量,定义、初始化可以放到for循环上面,num的迭代可以放到for循环里面。
for (int i = 0, num = 10; i < 5; ++i, ++num)
(2).不要比较指针类型的变量
指针变量的比较除了在数组里可能有意义,在其他大部分时候是没有意义的。
(3).不要在sizeof运算符中使用自增自减
增强可读性,避免出错。
(4).逻辑表达式中的每一个逻辑判断都加上括号
勤加括号,避免混淆不同运算符的优先级。
2、循环语句的效率
(1).对不同的情况使用适当的循环体
- 有明确循环次数,一般选择for循环
- 没有明确循环次数,一般选择while循环
- 至少循环1次,一般选择do while循环
(2).建议for循环采用“左闭右开区间”写法
不建议写成以下形式:
for (int i = 0; i <= 4; ++i)
建议写成以下形式:
for (int i = 0; i < 5; ++i)
(3).建议将高循环次数的循环置于嵌套循环的最内层
可以减少CPU跨切循环层的次数,从而优化程序性能。
(4).建议将高循环次数的循环体内的逻辑判断移到循环体外
3、if语句
(1).if语句独占一行,执行语句不得紧跟其后
(2).无论有几条执行语句,都要用大括号将执行语句括起来
便于以后的维护。
(3).else-if语句一定要包含最后的else节
增强可读性,避免出错。
4、switch语句
(1).switch语句独占一行
(2).每个case独占一行,执行语句不得紧跟其后
(3).若某个case没有break需要给出确认性注释
避免漏加而出错
(4).一定要有default语句
使switch语句完整。
(5).真假两种处理不应采用switch语句,应采用if语句
(6).case语句的先后顺序要使得执行次数尽可能少
各个case的顺序尽可能从以下顺序中选择有效的:
- 按出现频率的顺序,将频繁出现的处理放在前面
- 按照常见性的顺序,从通常的case到例外的case
- 按数值或字母的顺序
5、for语句
(1).for语句独占一行,执行语句不得紧跟其后
(2).无论有多少条执行语句,都必须用大括号将执行语句括起来
便于以后的维护。
(3).空的循环体要给出确认性注释
(4).循环计数尽量从0开始,不要从1开始。
(5).不要在循环体内强制变更循环变量
增强可读性,避免出错。
(6).for循环中禁用逗号运算符
增强可读性,避免出错。
(7).尽量避免在循环内申请/释放内存
防止产生内存泄漏。
6、while语句
(1).while语句独占一行,执行语句不得紧跟其后
(2).无论多少条语句都要用大括号将执行语句括起来
便于以后的维护。
(3).空的循环体要给出确认信解释
7、return语句
(1).return语句的返回值类型和函数声明的返回值类型相同
类型不同的时候可能会触发一个隐式强制类型转换。
但是在有些时候,将范围大的类型转换成范围小的类型时,会产生高位截断,如以下代码:
#include <cstdio>
char func()
{
int a = 0x1010;
return a;
}
int main()
{
char ch = func();
printf("%#x", ch); // 0x10
return 0;
}
(2).void返回值的函数return语句不应该有返回值
(3).建议一个函数一条返回语句
不建议使用下面的格式:
int func()
{
int a = 100;
if (a > 50)
return 100;
else
return 0;
}
建议使用下面的格式:
int func()
{
int res;
int a = 100;
if (a > 50)
res = 100;
else
res = 0;
return res;
}
(4).禁止使用goto语句
goto语句往往会破坏代码的执行结构,让代码难以理解,除了极少数的特殊的适用场景下,很少会用到。
有一种场景就是多个变量动态申请内存空间。
- 一开始的代码如下,这样写存在内存泄漏的问题,如果q申请空间失败,p的内存没有回收,就会有内存泄漏。
int func() { int *p, *q; p = (int*)malloc(4 * sizeof(int)); if (NULL == p) { printf("malloc fail\n"); return 0; } q = (int*)malloc(4 * sizeof(int)); if (NULL == q) { printf("malloc fail\n"); return 0; } return 1; }
- 因此,需要一个统一的申请失败终点,如以下代码
int func() { int *p, *q; p = (int*)malloc(4 * sizeof(int)); if (NULL == p) { printf("malloc fail\n"); goto End; } q = (int*)malloc(4 * sizeof(int)); if (NULL == q) { printf("malloc fail\n"); goto End; } return 1; End: if (NULL == p) { free(p); } if (NULL == q) { free(q); } return 0; }
类似的场景还有文件的打开。
8、初始化
(1).在enum类型中,将成员全部初始化/都不初始化/只初始化最前连续的几个
(2).初始化所有指针变量
9、代码格式
(1).函数的参数一般不要超过7个
从汇编角度来看,函数有4个参数时传递效率最高,因为在不超过4个参数的时候是通过寄存器来传递参数的,超过了就得借助栈空间来传递。
当参数过多时,应该考虑将参数定义为一个结构体,并将结构体指针作为参数
(2).函数的大小不要过长,一般定为350行以内(去除注释、变量定义、调试开关)
提高可读性,便于以后的维护,遵循函数设计原则。
(3).嵌套语句需要4字符的缩进
(4).用空行将代码逻辑片段进行划分
增加可读性。
(5).存储类型应该紧跟类型,而不是变量
存储类型有auto、static等。
举个例子,应该使用static int a;
而不是int static a;
(6).在声明和定义处,将指针、引用[*, &]紧跟类型,而不是变量
在这一点往往不同的公司要求不同。举个例子,一种是int* a
,另一种是int *a;
10.函数
(1).数组作为函数参数时,不需要指定数组大小
数组作为参数传递的是首地址,因此指定数组大小也是没有意义的。
(2).内定数据类型作为参数时,如果不需要修改就作为值传递而不是引用传递
(3).使用标准库<ctype.h>或<cctype>里的函数进行字符判断
提高代码效率,使代码更加精简。