嵌入式C语言编码规范参考

您所在的位置:网站首页 c语言代码软件下载 嵌入式C语言编码规范参考

嵌入式C语言编码规范参考

2024-03-25 20:35| 来源: 网络整理| 查看: 265

1 总则 1.1 目的

本规范主要目的是定义基于嵌入式C 编码的总体规范,确保编码的规范性,提高程序的可维护性。通过遵循共同的编码规范,程序开发人员可以保持代码一贯的风格,提高代码编写的可读性和使用的一贯性。

1.2 范围

适用于嵌入式C开发人员。

1.3 总体原则

在程序开发的过程中应当遵循以下几条总体原则:

1)文件须根据工程的需要分类进行统一存放,集中管理。

2)文件的命名应与工程保持协调,并能表达其内容最强烈的意向。(参见附录1)

3)文档文件、程序文件应精简适当,并保持完整的一致性、实时性。

4)标识符的命名要清晰、明了、直观、准确,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。

5)程序块要采用缩进风格编写。

6)注释的内容要清楚、明了,含义准确,源程序有效注释量在20%以上。

7)对变量进行恰当命名,使它成为自描述性的,以提高代码可读性。

8)明确函数功能,精确(而不是近似)地实现函数设计,函数的功能应单一,不可包含多种功能。函数名能准确描述函数的功能。

9)函数的返回值要清楚、明了,让使用者不容易忽视错误情况。**说明:**函数的每种出错返回值的意义要清晰、明了、准确,防止使用者误用、理解错误或忽视错误返回码。

10)注意编写高效、简洁的代码。

2 文件 2.1 规范

1) 文件须根据工程的需要分类进行统一存放,集中管理。

文件可大体分为下列几类:

程序文件:公共库,项目私有库,项目源码

编译输出文件:编译中间文件,编译可执行文件

工程配置文件:Makefile,keil配置文件

文档文件:需求,项目设计,测试,集成,资料参考,项目总结,其他。

2) 用户编写代码文件名全部小写,包括头文件(.h)和源文件(.c),汇编源文件(*.s)。

3) 头文件后缀为.h,源文件后缀为.c,汇编源文件后缀为.s,一个源码实现一个模块相关功能,不要包含其他无关代码。测试文件一律在命名中加_Test。

4) 对工程中常用到的结构、常量、全局变量声明等应单独存放为.h文件。

说明:对整个项目来说 需要针对模块细分。每个模块常用到的结构、常量和变量存放为该模块的.h文件,整个项目常用到的结构、常量和变量应存放为项目公用的.h文件。公用的.h放在公共目录下,比如include目录下

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

6) 用 #include 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。

7) 用 #include "filename.h" 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。

示例:

#ifndef GRAPHICS_H // 防止graphics.h被重复引用 #define GRAPHICS_H #include // 引用标准库的头文件 … #include “myheader.h” // 引用非标准库的头文件 … void Function1(…); // 全局函数声明 … #endif

8) 头文件中只声明而不定义。

9) 在非特殊情况下文件统一使用utf-8字符集编码。

2.2 建议

不提倡使用全局变量,尽量不要在头文件中出现象extern int value 这类声明。

3 标识符命名 3.1 规范

1) 一个项目中命名规范必须保持一致,建议使用unix命名或者驼峰法命名

2) 变量的名字应当使用“名词”或者“形容词+名词”。

示例,驼峰法:

float Value; float OldValue; float NewValue;

或者unix命名法:

float old_value; Float new_value;

3) 函数的名字应当使用“动词”或者“动词+名词”(动宾词组),

示例:

draw_box(); box->draw();

4) 命名中若使用特殊约定或缩写,则要有注释说明。

说明:对整个项目来说,应建立一个项目词汇表,统一管理出现的约定和缩写。

5) 尽量避免标识符中出现数字编号。

说明:有时为了计算或其他需要有数字编号的标识符,应加以详细说明。

示例:

如Value1,Value2等,除非逻辑上的确需要编号。

6) 程序中不要出现仅靠大小写区分的相似的标识符。

示例:

int x, X; // 变量x 与 X 容易混淆。

7) 对于变量命名,禁止取单个字符(如i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。

说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。

8) 函数的参数命名取更直接的名称。函数的参数建议在其名称后加_para,防止参数的偶然性被修改,也利于程序的阅读。

示例:

void setCurrent( int current_para ) { current = current_para; // 很清楚引用的是参数 }

9) 为了防止某一软件库中的一些标识符和其它软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀。例如USB所有库函数均以usb开头,所有常量(或宏定义)均以USB开头。(缩小为模块)

3.2 建议

标识符采用英文单词或其组合,切忌使用汉语拼音来命名,用词应当准确。

例如不要把CurrentValue写成NowValue。较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。

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

temp 可缩写为 tmp ; maximal 可缩写为 max ; flag 可缩写为 flg ; minimum 可缩写为 min ; statistic 可缩写为 stat; length 可缩写为 len ; increment 可缩写为 inc ; remove 可缩写为 rm ; message 可缩写为 msg ; delete 可缩写为 del ; dynamic 可缩写为 dyna; rectangle 可缩写为 rect; windows 可缩写为 win ; dialog 可缩写为 dlg ; image 可缩写为 img ; network 可缩写为 net ; transfers 可缩写为 trans; capacitance 可缩写为 capc ; parameter 可缩写为 para; source 可缩写为 src

11) 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。

说明:下面是一些在软件中常用的反义词组。

add / remove begin / end create / destroy insert / delete first / last get / release increment / decrement put / get add / delete lock / unlock open / close min / max old / new start / stop next / previous source / target show / hide send / receive source / destination cut / paste up / down

示例:

int min_sum; int max_sum; int add_user( BYTE *user_name ); int delete_user( BYTE *user_name );

12) 除了编译开关/头文件等特殊应用,应避免使用EXAMPLE_TEST之类以下划线"_"线开始和结尾的定义。

4 可读性 4.2 规范

1) 程序块要采用缩进风格编写,缩进为一个TAB键(TAB键设为4个空格字符)。

2) 较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;划分后的上一行末尾可用续行符 “\”与下一行保持良好的连续性。

示例1:

strcpy( msg, "###################################\ ######################" );

示例2:

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) 循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。

示例:

if ( ( taskno < max_act_task_number ) && ( n7stat_stat_item_valid ( stat_item ) ) ) { ... // program code } for ( i = 0, j = 0; ( i < BufferKeyword[word_index].word_length ) && ( j < NewKeyword.word_length ); i++, j++ ) { ... // program code } for ( i = 0, j = 0; ( i < first_word_length ) && ( j < second_word_length ); i++, j++ ) { ... // program code }

4) 若函数或过程中的参数较长,则要进行适当的划分。

示例:

n7stat_str_compare( ( BYTE * ) & stat_object, ( BYTE * ) & ( act_task_table[taskno].stat_object ), sizeof( _STAT_OBJECT ) ); n7stat_flash_act_duration( stat_item, frame_id *STAT_TASK_CHECK_NUMBER + index, stat_object );

5) 不允许把多个短语句写在一行中,即一行只写一条语句。

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

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

应如下书写

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

6) if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while、case等语句的执行语句部分无论多少都要加括号{}。

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

if ( pUserCR == 0 ) return; if( pUserCR == 1 ){ return; } else if ( pLeaderCR == 2 ) { pUserCR = 0; }

应如下书写:

if ( 0 == pUserCR ) { return; } if( pUserCR == 1 ) { return; } else if ( pLeaderCR == 2 ) { // else if 独占一行 pUserCR = 0; }

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

int i; switch ( i ) { case 0: //... break; case 1: //... break; default: break; }

应如下书写:

int i; switch ( i ) { case 0: { break; } case 1: { break; } default: { break; } }

7) 在switch语句中不要忘记最后那个default分支。即使程序真的不需要default处理,也应该保留语句 default : break; 这样做并非多此一举,而是为了防止别人误以为你忘了default处理。

8) 函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。

9) 在函数实现、类的定义、结构定义、枚举的定义以及if 、for、do、while、switch语句中的代码,要求’{‘和’}’各独占一行并且位于第一列,并与引用它们的语句左对齐,代码语句一般情况下要求采用缩进方式。

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

void example_fun( void ) { ... // program code }

应如下书写:

void example_fun( void ) { ... // program code }

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

for (...) { ... // program code } if (...) { ... // program code }

应如下书写。

for (...) { ... // program code }

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

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

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

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

示例:

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

int a, b, c;

(2) 比较操作符, 赋值操作符"="、 “+=”,算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符""、"."前后不加空格。

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

(5) if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。C关键字一般都要加空格,以突出关键字,也利于阅读和维护。

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

(6) 左括号"(“后 、右括号”)"前必须加空格。

11) 在每个函数定义结束之后都要加空行。

12) 源程序中逻揖上密切相关的语句尽可能相邻,并以空行与其他行相隔离。

示例:

while ( condition ) { statement1; // 空行 if ( condition ) { statement2; } else { statement3; } // 空行 statement4; }

示例:以下代码布局不太合理。

rect.length = 10; char_poi = str; rect.width = 5;

若按如下形式书写,可能更清晰一些。

rect.length = 10; rect.width = 5; // 矩形的长与宽关系较密切,放在一起。 char_poi = str;

13) 注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。

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

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

word = (high


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3