您的位置:首页 > 编程语言 > C语言/C++

安全级 C语言编程规范(草稿)

2008-07-02 21:09 281 查看
标准名称: C语言编程规范

标准编号:

版次号:A

受控号:

拟制:窦力争                2008 年  月  日

审核:                2008 年  月  日

批准:                2008 年  月  日

1 概述

为了保证公司在软件开发过程中,全体成员的代码减少隐患,风格一致,便于维护,提高软件产品的质量和保持开发产品的持续性,特制定本编码规范。

暂定本规范适用于                的C编码工作。

2 变量声明

2.1 变量的命名:

可以用多个英文单词拼写而成,每个英文单词的首写字母要大写,命名应当直观且可以拼读,可望文知意;变量的前缀表示该变量的类型。

类型	前缀	类型名称

bool	b	布尔型

(unsigned) char	(u)ch	(无符号)字符型

(unsigned) short	(u)sh	(无符号)短整型

(unsigned) int	(u)i	(无符号)整型

(unsigned) long	(u)l	(无符号)长整型

float	f	浮点型

point	p	指针

array	a	数组

string	str	字符串

Member	m_	成员变量

global	g_	全局变量

Static 	s_	静态变量

2.2宏定义和常量全用大写的字母,用下划线分割单词。

例如:

const int MAX = 100;

#define MAX_LENGTH  100

2.3静态变量加前缀s_(表示static)。

例如:

void Init(…)

{

static int s_initValue;	// 静态变量

…

}

2.4在可能的情况下减少全局变量的使用,全局变量加前缀g_(表示global)。例如:

int g_iManyPeople;	// 全局变量

2.5 类型转换:

尽量避免强制类型转换;如果不得不作类型转换,尽量用显式方式。

2.6必须在定义变量的同时初始化该变量

如果变量的引用处和其定义处相隔比较远,变量的初始化很容易被忘记。如果引用了未被初始化的变量,可能会导致程序错误。所以本条可以减少隐患。且曾强其代码可测性。

3 基本语句

3.1不可在for 循环体内修改循环变量,防止for 循环失去控制。(指南)

3.2 不准使用switch 语句。(1058)

3.3不要使用goto语句。(1058)

3.4 不得使用三元操作符(MISRA)

3.5不得残留被注释掉的废代码。(MISRA)

3.6所有标识符不得超过31字符。(MISRA)

3.7禁止使用八进制数。(因为086U这样的常数很容易引起误解)。(MISRA)

3.8在同一个编译单元中,同一个标识符不应该同时具有内部链接和外部链接的声名。(MISRA)

3.9具有外部链接性质的标识符应该只声明一次。(MISRA)

3.10外部对象不得在多个文件中声名。(MISRA)

3.11禁止使用register关键字。(MISRA)

3.12自动对象(栈对象)使用前必须赋初值。(MISRA)

3.13 操作符&&和||的右侧表达式不得具有副作用(side-effect)。也就是说,      象 if (x == 20 && ++y == 19)这样的表达式被禁止。(MISRA)

3.14在返回布尔值的表达式中不得出现赋值操作。也就是说,我们常用的 if       (!(fp = fopen("fname", "r"))) { /* error */ }被禁止。(MISRA)

3.15不得对有符号数施加位操作,例如 1 << 4 将被禁止,必须写 1UL << 4; (MISRA)

3.16不得对有符号表达式施加一元 "-" 非操作符。(MISRA)

3.17 禁止冗余的显式转型。比如: double pi = (double) 3.1416F; (MISRA)

3.18禁止从任意类型到指针的强制转型,禁止从指针到任意类型的强制转型。例如:void* p = (void*)0xFFFF8888UL; (MISRA)

3.19不得遗留“永远不会用到”的代码。(MISRA)

3.20循环计数器的值不得在循环体内修改。(MISRA)

3.21每个函数只能有一个推出点。(MISRA)

3.22在一个宏定义中,#或##符号只能出现一次。(MISRA)

3.23禁止指针运算(代之以数组下标运算)。(MISRA)

3.24禁止超过两级的指针。(MISRA)

3.25禁止使用指向函数的非常量指针。(MISRA)

3.26不得将栈对象的地址传给外部作用域的对象。(MISRA)

3.27禁止使用动态堆分配(也就是不得使用malloc, calloc和realloc)。(MISRA)

3.28禁止使用errno。(MISRA)

3.29禁止使用offsetof. (MISRA)

3.30禁止使用<locale.h>。(MISRA)

3.31禁止使用setjmp, longjmp. (MISRA)

3.32禁止使用<signal.h>(MISRA)

3.33禁止使用<stdio.h>(不能用printf, scanf了!)(MISRA)

3.34禁止使用atoi, atof, atol。(MISRA)

3.35禁止使用abort, exit, getenv。(MISRA)

3.36禁止使用<time.h>。(MISRA)

3.37禁止使用#undef。(MISRA)

3.38 不得使用标号(label)。(MISRA)

3.39 不得使用continue。(MISRA)

3.40 不得使用 break。(MISRA)

3.41 禁止任何直接或间接的递归函数调用。(MISRA)

3.42不允许重复代码出现,三行以上代码,重复出现两次以上,必须将这段代码封装为函数,以备重复调用。尽量保证代码的简洁性。

3.43不可将浮点变量用“==”或“!=”与任何数字比较。(指南)

4 结构体和指针

4.1 结构体初始化和善后都要清空,如:

memset(&STRUCT1, 0, sizeof(STRUCT1));

5 函数设计

5.1 函数体的规模必须控制在200行代码之内,单个函数的分支路径控制在10条以内; 除了函数入口处的参数合法性检查外,函数内的控制流保持函数只有唯一出口。

5.2 函数返回值:

显式定义返回类型,如果不是void,任何情况下都要有返回值;

尽量用宏定义或约定以-1、0等统一表示错误的返回值;如果返回值可能有很多个,都进行宏定义。

对重要的被调函数,调用后应该判断其返回值,确定执行是否成功。

5.3如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。

例如:

void StringCopy(char *strDestination,const char *strSource);

5.4 避免函数有太多的参数,参数个数尽量控制在5个以内(如果有个别函数加此限制会增加复杂度,那么允许超过5个参数,但这类函数占整个软件的百分比必须<5%)。如果参数太多,在使用时容易将参数类型或顺序搞错。

5.5 尽量不要使用类型和数目不确定的参数。

C标准库函数printf是采用不确定参数的典型代表,其原型为:

int printf(const chat *format[, argument]…);

这种风格的函数在编译时丧失了严格的类型安全检查。

5.6 应采用简单的算术表达式代替复杂的算术表达式。(1058)

5.7 数组寻址时,应检查其边界。(1058)

5.8 在函数开头应对函数参数传输的正确性进行检查,包括参数类型。(1058)

5.9 子程序应只通过参数与他们的环境通讯。(1058)

5.10 子程序应只有一个入口。(1058)

5.11 应避免使用嵌套宏指令。(1058)

5.12 每一种数据类型应只采用一种寻址方法。(1058)

5.13 应避免繁杂的变址计算(1058)

5.14如果要嵌入汇编语言,则必须将所有汇编语句包装在C函数里,而且这些函数中只有汇编语句,没有常规C语句。(指南)

5.15循环、分支层次不要超过五层。(指南)

6 程序版式

6.1每个函数之前和之后都必须加空行。(指南)

6.2在一个函数体内,逻辑上密切相关的语句之间不加空行,其它地方应加空行分隔。(指南)

6.3一行代码只做一件事情。如只定义一个变量,或只写一条语句。(指南)

6.4 if、for、while、do等语句自占一行,后面即使只有一条执行语句。特别是有条件判断else if嵌套的地方,更应该注意,以免套混了。(指南)

6.5避免定义的变量不使用,特别是一些临时变量。(指南)

6.6程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。(指南)

6.7程序应采用缩进风格编写,每层缩进使用一个制表位(TAB)。

void Function(int x)

{

… // program code

}

void Function(int x){

… // program code

}

if (condition)

{

… // program code

}

else

{

… // program code

}	if (condition){

… // program code

}

else {

… // program code

}

示例(a) 风格良好的对齐         示例(b) 风格不良的对齐

6.8一行代码最大长度宜控制在80个字符以内。(指南)

6.9每个重要语句都必须有注释。注释是说明一段代码的目的,而不是重复每一句代码;注释用词要精确,不能有二义性;同时注意及时更新注释,以保证注释与代码的一致性。

6.10当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。如下:

if (…)

{

…

while (…)

{

…

} // end of while

…

} // end of if

6.11源程序头的注释规范:

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

* Copyright (c) 2007,          限公司

* All rights reserved.

* 文件名称:

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

* 当前版本:1.1

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

* 完成日期:2001年7月20日

*

* 取代版本:1.0

* 原作者 :输入原作者(或修改者)名字

* 完成日期:2001年5月10日

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

函数头的注释和规范:

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

*功能: (说明函数的功能)

*参数: (说明每个输入输出参数的用途和取值约定)

*返回值: (说明返回值的含义和约定)

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

6.12 头文件必须使用ifndef/define/endif结构产生预处理块,为了防止头文件被重复引用。(指南)

6.13 用 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。(指南)

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

附录1

参考标准文献:

1.《IEC 60880 NORME INTERNATIONALE INTERNATIONAL STANDARD》

2.《EJ/T 1058 核电厂安全系统计算机软件》

3. 《MISRA工业标准C语言编程规范》

4.《高质量C++/C编程指南》 (林锐)

附录2

规范中标记:

1.MISRA  :汽车工业软件可靠性联会

2.1058   :核电厂安全系统计算机软件 EJ/T 1058

3.指南   :《高质量C++/C编程指南》 (林锐)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: