华为c语言编程规范是怎样的

Python013

华为c语言编程规范是怎样的,第1张

代码总体原则

清晰第一。清晰性是易于维护、易于重构的程序必须具备的特征。

简洁为美。简介就是易于理解并且易于实现。

选择合适的风格,与源代码风格保持一致。

头文件

头文件的设计体现了大部分的系统设计,不合理的头文件布局是编译时间过长的根因,实际上是不合理的设计。

头文件中适合放置接口的声明,不适合放置实现。

头文件应当职责单一。

头文件应向稳定的方向包含。

每一个.c文件应有一个同名的.h文件,用于声明需要对外公开的接口。

禁止头文件循环依赖。

禁止包含用不到的头文件。

头文件应当自包含。

编写内部#include保护符(#define保护)。

禁止在头文件中定义变量

只能通过包含头文件的方式使用其他C提供的接口,禁止在C中通过extern的方式使用外部函数接口和变量。

禁止在extern "C"中包含头文件。

函数

函数设计的精髓:编写整洁函数,同事把代码有效组织起来。

一个函数仅完成一个功能。

重复代码应该尽可能提炼成函数。

避免函数过长,新增函数不超过50行。

避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。

可重入函数应避免使用共享变量;若需要使用,则应该通过互斥手段对其加以保护。

对参数的合法性检查,由调用者负责还是接口函数负责,应在项目组模块内统一规定。缺省由调用者负责。

对函数的错误返回码要全面处理。

设计高扇入,合理扇出(小于7)的函数。扇出是指调用其它函数的数目。扇入是指有多少上级函数调用它。

废弃代码要及时清除。

函数参数不变使用const限定。

函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用。

检查函数所有非参数输入的有效性,如数据文件、公共变量等。

函数的参数个数不超过5个。

在源文件范围内声明和定义的所有函数,除非外部可见,否则应该加static关键字。

标识符

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

产品、项目组内应保持同意的命名分格。

尽量避免名字中出现数字编号,除非逻辑上确实需要。

重构、修改部分代码时,应该保持和原有代码风格一致。

文件命令统一采用小写字符。因为不同系统对文件名大小写处理会有不同(windows不区分大小写,但是linux系统则区分)。

全局变量应增加“g_”前缀。

静态变量应增加“s_”前缀。

禁止使用单字节命名变量,但是允许定义i,j,k作为局部循环变量。

不建议使用匈牙利命名法。

对于数值或者字符串常量的定义,建议采用全大写字母,单词之间加下划线的方式命名。

变量

结构功能单一,不要设计面面俱到的数据结构。

不用或者少用全局变量

防止局部变量与全局变量同名

通讯过程中使用的机构,必须注意字节序。

严禁使用未经初始化的变量作为右值。

使用面向接口编程思想,通过API访问数据。

尽量减少没有必要的数据类型默认转换与强制转换。

宏和常量

用宏定义表达式时,要使用完备的括号。

将宏定义的多条表达式放在大括号中。

使用宏时,不允许参数发生变化。

不允许直接使用魔鬼数字。

除非必要,应尽可能使用函数代替宏。

常量建议用const定义代替宏。

质量

时刻注意易混淆的操作符

必须了解编译系统的内存分配方式,特别是编译系统对不同类型的变量的内存分配规则,如局部变量在何处分配、静态变量在何处分配等。

不仅关注接口,同样要关注实现。

禁止内存操作越界。

禁止内存泄漏。

禁止引用已经释放的内存空间。

编程时,要防止差1错误。

switch语句必须有default分支。

函数中分配的内存,在函数退出之前要释放。

不要滥用goto语句。

时刻注意表达式是否会上溢、下溢。

程序效率

在保证软件系统的正确性、简洁、可维护性、可靠性及可测试性的前提下,提高代码的效率。

通过对数据结构、程序算法的优化来提高效率。

将不变条件的计算移到循环体外。

对于多维大数组,避免来回跳跃式访问数组成员。

创建资源库,以减少分配对象的开销。

将多次被调用的“小函数”改为inline函数或者宏实现。

注释

优秀的代码可以自我解释,不通过注释即可轻易读懂。

注释的内容要清楚、明了,含义准确,防止注释二义性。

修改代码时,维护代码周边的所有注释,以保证注释与代码的一致性。不再有用的注释要删除。

文件头部应进行注释,注释需要列出:版权说明、版本号、生成日期、作者姓名、工号、内容、功能说明、与其他文件的关系、修改日志等,头文件的注释中还应有函数功能的说明。

函数声明处注释描述函数功能、性能及用法,包括输入和输出参数、函数返回值、可重入的要求等;定义处详细描述函数功能和实现要点,如实现的简要步骤、实现的理由、设计约束等。

全局变量要有详细的注释,包括对其功能、取值范围以及存取时注意事项等的说明。

尽量采用工具可以识别的格式注释。

排版与格式

程序块采用缩进风格编写,每级缩进为4个空格。

相对独立的程序块之间、变量说明之后必须加空行。

一行只写一条语句。

对等操作两边加空格,注释符与内容之间加空格。

编译

使用编译器的最高告警级别,理解所有的告警,通过修改代码而不是降低告警级别来消除所有告警。

在产品软件中,要统一编译开关、静态检查选项以及相应告警清除策略。

可测性

模块划分清晰,接口明确,耦合性小,有明确输入和输出,否则单元测试实施困难。

在统一项目组或产品组内,调测打印的日志要有统一的规定。

使用断言记录内部假设。

不能用断言来检查运行时错误。

伪码书写可以参考C代码规范。

1.

1.1符号命名规则

1.1.1符号名包括模块名、常量名、标号名、子程序名等。这些名字应该能反映它所代表的实际东西,具有一定的意义,使其能够见名知义,有助于对程序功能的理解。命名采用匈牙利命名法。规则如下:

(1)所有宏定义、枚举常数和const变量,用大写字母命名。在复合词里用下划线隔开每个词。

(2)复合词中每个单词的第一个字母大写。除了规则5.1.1.1以外,避免使用下划线。

(3)类、类型定义和枚举型名的第一个字母大写。

(4)函数名是复合词的,第一个词采用全部小写,随后每个单词采用第一个字母大写,其它字母小写方式;如果是单个词的,采用全部小写方式。

(5)循环变量可采用i, j, k等,不受上述规则限制。

(6) 类的成员变量应采用m_开头。

(7) 全局变量词头为g_ 。

(8) 临时变量词头为tmp_ 。

(9) 对结构体内的变量命名, 遵循变量的具体含义命名原则

(10)用小写字母的前缀表示变量的类型,前缀的下一个字母用大写。

表 1

词头 类型 词头类型

ch charl long

i integer u unsigned

b boolean p pointer

f float lplong pointer

d double s string

st structure szASCII string

by byten short int

H handle x,y分别为x,y坐标

dw DWORD fnfunction

表 2

词头 变量名 词头 变量名

task tasksig signal

sbbinary semaphores wd watchdog

smmutual exclusion tm timer

sccounting semaphores msg message

pipe pipe

例:

#define ARRAY_SIZE 24 /*规则5.1.1.1*/

int g_iFlag

class MyClass /*规则5.1.1.3*/

{

}

void someFunc( ) /*规则5.1.1.2和5.1.1.4*/

{

int nArray[ARRAY_SIZE]

unsigned char uchByte

char szName[ ]

char *pszName = szName

}

(11)有些词头(如p和u)可以和其它词头组合。

例:WDOG_ID wdId

WDOG_ID g_wdId /*全局watchdog Id,故以g_开头*/

1.1.2名字的长度一般不要过长或过短。过长的名字会增加工作量,使程序逻辑流程变得模糊;过短的名字无法表达符号的实际意义。约定长度范围:3-31;

1.2数据和函数说明

1.2.1数据说明次序应当规范化,使数据属性容易查找,也有利于测试、排错和维护。说明的先后次序应固定,应按逻辑功能排序,逻辑功能块内建议采用下列顺序:整型说明、实型说明、字符说明、逻辑量说明。

1.2.2如果设计了一个复杂的数据结构,应当通过注释对其变量的含义、用途进行说明。

1.2.3在函数的声明中使用异常声明。

如:void f() throw(toobig, toosmall, divzero)

在声明一个函数时,将它所抛出的异常列出,便于函数的使用者了解可能会发生哪些异常。

1.3 程序注释

1.3.1程序注释是程序员与日后的程序读者之间通信的重要手段之一,注释分为文件注释、函数注释和功能注释。

1.3.2正规程序的注释应注意:

——注释行的数量占到整个源程序的1/3到1/2。

1.3.3文件注释位于整个源程序的最开始部分,注释后空两行开始程序正文。它包括:

——程序标题。

——目的、功能说明。

——文件作者、最后修改日期等说明。

例:

./********************************************************************

(空一行)

标题: Demo.c

功能: 测试VxWorks的各种系统调用.

说明:

该程序测试各种VxWorks的系统调用函数。包括任务(taks)的创建、挂起及任务间通过信号灯实现同步,通过消息队列 进行通讯。

程序创建了两个任务:一个高优先级的任务和一个低优先级的任务。两个任务间通过一个二进制的信号灯进行同步,通过消息队列进行通讯。

当前版本: x.x

修改信息: 2000.06.05 John, Initial Version

2000.07.05 Tom, Bug xxxx fixed

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

(空2行,开始程序正文)

1.3.4 函数注释通常置于每函数或过程的开头部分,它应当给出函数或过程的整体说明对于理解程序本身具有引导作用。一般包括如下条目:

——模块标题。

——有关本模块功能和目的的说明。

——调用格式

——接口说明:包括输入、输出、返回值、异常。

——算法。如果模块中采用了一些复杂的算法。

例:

file://(/注释开头应和上一函数空两行)

(注释开头与上一函数最后一行间隔两行)

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

标题:assignmentComplete

功能:BSC=>MSC消息生成函数,生成assignment_complete指配完成消息(BSMAP消息) .

格式:

int assignmentComplete(int iCellId, int iServiceChannnelNum, char *pszMSGData) throw(exception1, exception2)

输入:

int iCellId: MS所在的小区识别

iCellId取值:0x00-——0xff

int iServiceChannnelNum:MS所占的业务信道号码

输出:

char * pszMSGData:指配完成消息数据

返回值: 0x00正常

异常:exception1异常情况1, exception2异常情况2

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

( 注释后直接开始程序正文,不空行。)

1.3.5功能性注释嵌在源程序体中,用于描述其后的语句或程序段做什么工作,也就是解释下面要做什么,或是执行了下面的语句会怎么样。而不要解释下面怎么做,因为解释怎么做常常与程序本身是重复的。

例:

/*把 amount 加到 total中*/

total = amount + total

这样的注释仅仅是重复了下面的程序,对于理解它的工作并没有什么作用。而下面的注释,有助于读者理解。

/*将每月的销售额amount加到年销售额total中*/

total = amount + total

1.4 函数编写应尽可能短小精悍,一般不超过两屏,以便于调试和理解。

1.5语句结构

为保证语句结构的清晰和程序的可读性,在编写软件程序时应注意以下几个方面的问题:

——在一行内只写一条语句,并采用空格、空行和移行保证清楚的视觉效果。

——每一个嵌套的函数块,使用一个TAB缩进(可以设定为4个空格),大括号必须放在条件语句的下一行,单独成一行,便于匹对:

如,有一段程序如下:

for(i=1i<n-1i++){ t=1for(j=i+1j<nj++){

if(a[j]<a[t] ) t=jif(t!=i ){work=a[t]a[t]=a[I]a[I]=work}}}

应写为

for( i=1i<n-1i++)

{

t=1

for(j = i+1j<nj++)

{

if(a[i]<a[j])

t=j

if(t!=1)

{ .5.

Q/ECC/BJ 010—2001

work=a[t]

a[t]=a[i]

a[i]=work

}

}

}

——文件之中不得存在无规则的空行,比如说连续十个空行。

一般来讲函数与函数之间的空行为2-3行;

在函数体内部,在逻辑上独立的两个函数块可适当空行,一般为1-2行。

——程序编写首先应考虑清晰性,不要刻意追求技巧性而使得程序难以理解。

——每行长度尽量避免超过屏幕宽度,应不超过80个字符。

——除非对效率有特殊要求,编写程序要作到清晰第一,效率第二。

——尽可能使用函数库。

——尽量用公共过程或子程序去代替重复的功能代码段。要注意,这个代码应具有一个独立的功能,不要只因代码形式一样便将其抽出组成一个公共过程或子程序。

——使用括号清晰地表达算术表达式和逻辑表达式的运算顺序。如将 x=a*b/c*d 写成 x=(a*b/c)*d可避免阅读者误解为x=(a*b)/(c*d)。

——避免不必要的转移。

——避免采用过于复杂的条件测试。

——避免过多的循环嵌套和条件嵌套。

——建议不要使用 *=,^=, /=等运算符。

——一个函数不要超过200行。一个文件应避免超过2000行。

——尽量避免使用go to语句。

——避免采用多赋值语句,如x = y = z

——不鼓励采用?:操作符,如z = (a>b)?a:b

——不要使用空的if else 语句。如

if(cMychar >= ‘A’)

if(cMychar <= ‘Z’)

printf(“This is a letter \n”)

else

printf(“This is not a letter \n”)

else到底是否定哪个if容易引起误解。可通过加{}避免误解。

——尽量减少使用“否定”条件的条件语句。如:

把 if( !( (cMychar<’0’) || (cMychar>’9’) ) )

改为if( (cMychar>=’0’) &&(cMychar<=’9’) )

这是两种不同的风格,并没有更规范一说

有的大牛认为第一种比较好 有的大牛认为第二种比较好 争来争去,这个不会有最终结论的。

你习惯那种就使用那种就可以了,如果你是和别人一个团队进行开发,随着团队的风格来就可以了。