一、排版
1. 程序块采用缩进的风格编写,注意TAB键的缩进空格数,不同IDE下,注意设置TAB键的空格数,我们采用缩进的空格数为4个。
2. 相对独立的程序块、变量说明之后加空行,以示区分相对独立性。
3. 较长的语句(超过80字符)要分行书写,长表达式要在低优先级操作符处换行,操作符位于新行之首,并进行适当的缩进,总之原则使得排版整齐,逻辑关系清晰,增强代码的可读性。循环语句、判断语句中如果判断条件较长、较复杂,要采用换行划分的方式,增强可读性,不引起歧义。
4. 遵循一行一语句的原则,不将多个短语句(例如赋值语句)写在同一行。
5. 循环、判断语句的执行语句,无论多少(即使空语句),也要加括号{};if,for,do,while ,case,switch,default等语句自占一行。
6. 同一组{}的左右括号,采用列左对齐的书写风格,并且不同组的{}之间采用缩进。
7. 用好空格键,可以提高代码的清晰性,凸显代码之间的独立性和关联性。
Ø 双目、三目运算符前后加空格
a = b + c;
Ø 单目运算符,结构体/结构体指针的成员运算符前后不加空格
i++; p = &a; p->No = 100; student.No = 100;
Ø 变量定义时,逗号后面加空格
int a, b, c;
Ø if,for,while ,switch等关键字后面加空格,凸显关键字,
if (a > b || c < d)
Ø 左括号的后面、右括号的前面不用加空格。
二、对于注释:
1. 注释的意义在于解释代码的目的、功能和实现方法,其描述应准确、易懂、简洁;注释中不出现于代码无关的信息,例如日期、姓名等;注释尽量采用中文。
2. 函数头部的注释说明的格式,参考如下:
/*************************************************
Description: // 函数功能、性能等的描述
*************************************************/
3. 对单条语句的注释放在右方,缩进4个空格(1个TAB键);对程序块的注释放在上方,与程序块的缩排相同,且与上面的代码用空行隔开。
4. 函数、变量、常量等命名尽量清晰准确,实现自注释,减少不必要的注释,提高注释的有效性。
5. 注释不求面面俱到,但对程序中关键的常量、变量定义、条件分支要加注释说明。
6. 目前注释方式统一采用//。
三、标识符命名
1. 标识符的命名要清晰、明了,尽量能望文生义;缩写的单词要通用,较短的单词可通过去掉元音字母形成缩写,较长的单词可取单词的头几个字母形成缩写。
2. 标识符的命名规范如下
Ø 宏定义全大写,在单词之间加下划线
#define PI 3.1415926
#define SERVO_PASSWORD 123456
Ø 函数名采用驼峰法,以大写字母开头,如
void BlockInitEncFdb(void);
Ø 需要体现函数所属模块时,可在前面加大写模块名并用下划线隔开
Uint16 DDI_ReadAdcReg(Uint16 sampleChannel)
Ø 结构体名全大写并在单词之间加下划线,或使用驼峰命名法。两种方式均在名称前加s_,如
typedef struct
{
} s_EncFdbCalcPriObj;
typedef struct
{
} s_ENC_FLAG;
Ø 全局变量或静态变量,采用首字母小写、大小写混排的方式,全局变量以g开头,静态变量以s开头,如
Uint16 gCurrLoop;
static Uint16 sCurrLoop;
Ø 函数的形参、局部变量采用驼峰命名法,以小写字母开头,如
Uint16 tmpTheta, sinTheta, cosTheta;
1. 结构体的功能要单一,是针对一种事务的抽象,结构体中的元素应代表同一事务的不同属性,不应把没有关系或者关系很弱的元素放在一个结构体中。
2. 若结构体中元素个数过多,可考虑根据某种原则把元素组成不同的子结构,以增强结构体的可理解性、可操作性和可维护性。
3. 对于标志位、状态位类的结构体,使用位域进行定义,节省占用空间。
五、函数
1. 函数是系统模块划分的产物,因此函数应具有高内聚低耦合的特性,一个函数完成某一项特定的功能。
2. 避免函数中不必要的的语句,减少垃圾代码,节省空间效率。
3. 函数中尽量避免使用全局变量,通过定义模块内的静态变量,使用形参传递等方式规避。
4. 尽量不要把与函数返回值类型不同的变量,以便以系统默认的转换方式或强制的转换方式作为返回值返回。
5. 对于需要多个返回值的情形,可考虑使用指向结构体的指针实现。
6. 一个函数的规模应控制在200行以内(不含注释与空行)。
7. 函数的命名方式、函数的注释说明见上文。
六、代码运行效率
1. 注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级,增强可读性。
2. 用有意义的标识来替代不易理解的数字,用直观的宏来替代。
#define MODE 0x0001
#define DATA 0x0008
3. 程序中关系紧密的代码应尽可能相邻,与流程图设计相一致。
4. 由于循环体语句执行的流程,应使循环体内工作量最小,例如逻辑上与循环无关的赋值语句、判断语句等,应将其从循环体内移出,从而提高程序的时间效率;但程序的空间效率与时间效率有时是矛盾的。
for (i = 0; i < 100; i++)
{
a[i] = 1;
}
相比 a[0] = 1; …………; a[99] = 1; 空间效率是优化的,但时间效率是不足的。
5. 尽量减少循环嵌套的层次,在多重循环中,应将最忙的循环放在最内层。
6. 紧凑的代码,高技巧的代码,不代表高效的机器码,高执行效率的软件设计。
7. 代码效率的提升不要过分依赖编程技巧、拘泥于局部的效率提升;应从大局上选择核心算法的模型、根据系统功能需求设计软件架构与处理机制、模块的划分,频繁调用模块的高效设计。
七、其他
1. 关于编译(Compiler),同一项目中使用相同的编译选项,包括编译器的版本、编译的形式(Debug、Release)、编译的优化等级等编译选项的设置。
2. 关于链接(Linker),同一项目调用相同的库文件、使用相同的输出文件的命名规范、堆栈的大小。
3. 关于条件编译(版本控制)、编译开关(代码调试)等预处理命令,采用全大写加下划线的方式,如
#ifdef DEBUG_TEST
#if DRV_TYPE == DRV_1KW
4. 头文件的格式,为防止被重复包含,采用如下标准的格式
#ifndef __FPGA_H__
#define __FPGA_H__
#endif // end of _FPGA_H definition
5. 对数据类型进行恰当命名,使其成为子描述性的,命名方式在同一项目中统一
typedef signed int int16
typedef signed long int int32
typedef signed long long int int64
typedef unsigned int Uint16
typedef unsigned long int Uint32
typedef unsigned long long int Uint64
typedef float float32
typedef long double float64
掌握所使用编译系统,对不同数据类型的长度和数据范围,减少无谓的数据类型默认转换和强制转换。e.g