嵌入式软件编程规范


1、程序块要采用缩进风格编写,缩进的空格数为4个。不使用TAB键。

说明:函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。Tab键在不同编译环境下可能设置的空格数不同,所以尽量不使用。

2、函数参数或者较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

示例:

perm_count_msg.head.len = NO7_TO_STAT_PERM_COUNT_LEN

                          + STAT_SIZE_PER_FRAM * sizeof( _UL );

 

act_task_table[frame_id * STAT_TASK_CHECK_NUMBER + index].occupied

              = stat_poi[index].occupied;

 

act_task_table[taskno].duration_true_or_false

              = SYS_get_sccp_statistic_state( stat_item );

 

report_or_not_flag = ((taskno < MAX_ACT_TASK_NUMBER)

                      && (n7stat_stat_item_valid (stat_item))

                      && (act_task_table[taskno].result_data != 0));

3、不允许把多个短语句写在一行中,即一行只写一条语句。iffordowhilecaseswitchdefault等语句自占一行,且iffordowhile等语句的执行语句部分无论多少都要加括号{},并且每个半括号都独占一行。 

示例:如下例子不符合规范。

rect.length = 0;  rect.width = 0;

if (pUserCR == NULL) return;

 

应如下书写:

rect.length = 0;

rect.width  = 0;

 

if (pUserCR == NULL)

{

    return;

}

 

4、在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。

说明:采用这种松散方式编写代码的目的是使代码更加清晰。

由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C++语言中括号已经是最清晰的标志了。

在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。

 

示例:

(1) 逗号、分号只在后面加空格。

int a, b, c;

 

(2)比较操作符, 赋值操作符"="、 "+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"<<"、"^"等双目操作符的前后加空格。

if (current_time >= MAX_TIME_VALUE)

a = b + c;

a *= 2;

a = b ^ 2;

 

(3)"!"、"~"、"++"、"--"、"&"(地址运算符)等单目操作符前后不加空格。

*p = 'a';        // 内容操作"*"与内容之间

flag = !isEmpty; // 非操作"!"与内容之间

p = &mem;        // 地址操作"&" 与内容之间

i++;             // "++","--"与内容之间

 

(4)"->"、"."前后不加空格。

p->id = pid;     // "->"指针前后不加空格

 

(5) if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。

if (a >= b && c > d)

 

5、源文件及说明性文件(如.c文件、.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。

示例:下面这段源文件的头注释比较标准,可以直接复制到文件中

/*

* Copyright (c) 2020,XXX有限公司

* All rights reserved.

* 文件名称:filename.h

* 文件标识:

* 开发环境:

* 描    述:简要描述本文件的内容,

*

* 当前版本:V1.0

* 作    者:作者(或修改者)名字

* 更改说明:说明创建/更改内容等

* 完成日期:2020年4月21日

*

* 修改记录 

*  作者   时间    版本      修改描述

*  

*/

  1. 函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等,对于很简单的函数可以只列出其中部分,但是不能缺失注释。

示例:下面这段函数的注释比较标准/*************************************************

  函数名称:         // 函数名称

  功能描述:         // 函数功能、性能等的描述

  子 函 数:          // 被本函数调用的函数清单

  调用限制:          // 调用本函数的注意事项,如需要满足的条件,先后顺序或者调//用清单等

  输入参数:          // 输入参数说明,包括每个参数的作

                      // 用、取值说明及参数间关系。

  输出参数:           // 对输出参数的说明。

  返 回 值:           // 函数返回值的说明

  说    明:            // 其它说明

*************************************************/

7、对于数据结构声明(包括数组、结构、类、枚举等)所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方,则需与其上面的代码用空行隔开。避免在一行代码或表达式的中间插入注释不使用非常用的注释,并且注释与所描述内容使用同样的缩进。

示例:如下例子不符合规范。

例1:

/* get replicate sub system index and net indicator */

    

repssn_ind = ssn_data[index].repssn_index;

repssn_ni = ssn_data[index].ni;

 

例2:

repssn_ind = ssn_data[index].repssn_index;

repssn_ni = ssn_data[index].ni;

/* get replicate sub system index and net indicator */

 

应如下书写

/* get replicate sub system index and net indicator */

repssn_ind = ssn_data[index].repssn_index;

repssn_ni = ssn_data[index].ni;

8、标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解,对于变量命名,禁止取单个字符(如ijk...),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但ijk作局部循环变量是允许的,用正确的反义词组命名具有互斥意义的变量或相反动作的函数。

说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。

示例:如下单词的缩写能够被大家基本认可。

temp 可缩写为  tmp  ;

flag 可缩写为  flg  ;

statistic 可缩写为  stat ;

increment 可缩写为  inc  ;

message 可缩写为  msg  ;

变量第一个字母小写,后具有独立意义的单词第一个字符大写,其他字符小写;静态变量前加小写s,全局变量前加小写g,全局变量名还应加上数据类型说明字符;函数名、类名、结构名第一个字符大写,后具有独立意义的单词第一个字符大写,其他字符小写;常数及宏定义字符全部大写,并用下划线连接。举例:

u8   maxValue;//局部变量

u16  u16gRegTask1ms;//u16的全局变量

s8   s8gMinValue;//s8类型的全局变量

u16  sValue//静态变量

u8   GetMaxValue(u8 Value1,u8 Value2);//函数

#define PI 3.1415926 

typedef  struct

{

u16  Read( u8  *PData, u16 Len);

u16  Write( u8   *PData, u16 Len);

}  TypeDevSPI;

TypeDevSPI   gSPI;//全局结构

 

不建议使用bool类型

 

9、在多重循环中,应将最忙的循环放在最内层,避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级,不要使用难懂的技巧性很高的语句,除非很有必要时。

说明:防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。

示例:下列语句中的表达式

word = (high << 8) | low     (1)

if ((a | b) && (a & c))      (2)

if ((a | b) < (c & d))       (3)

如果书写为

high << 8 | low

a | b && a & c

a | b < c & d

由于

high << 8 | low = ( high << 8) | low,

a | b && a & c = (a | b) && (a & c),

(1)(2)不会出错,但语句不易理解;

a | b < c & d = a | (b < c) & d,(3)造成了判断条件出错。

这也不合规范

* stat_poi ++ += 1;

* ++ stat_poi += 1;

应分别改为如下。

*stat_poi += 1;

stat_poi++;     // 此二语句功能相当于“ * stat_poi ++ += 1; ”

10、使用严格形式定义的、可移植的数据类型,尽量不要使用与具体硬件或软件环境关系密切的变量。

说明:使用u8、u16、u32、s8、s16、s32等形式表示

11、有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支,不要滥用goto语句。

12、头文件中只存放“声明”而不存放“定义”

为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。

 

 

发布了1 篇原创文章 · 获赞 0 · 访问量 4

猜你喜欢

转载自blog.csdn.net/qq_16098783/article/details/105718496