安全级 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编程指南》 (林锐)
相关文章推荐
- CERT Secure Coding Standard — C语言安全编程规范
- 编程规范建议(C语言)
- 华为C语言编程规范(8)—程序效率
- 华为C语言编程规范(5)—可读性
- 华为C语言编程规范(2)—排版
- C语言编程规范 [注释]
- 简图记录-C语言编程规范:可读性、安全性、可移植性
- 华为C语言编程规范—程序效率
- 华为C语言编程规范—质量保证
- [草稿]浅谈通用软件中的数据安全问题(C语言)
- 单片机开发之C语言编程基本规范
- c语言编程规范和范例
- C语言编程规范5: 预编译宏
- VC编程规范[转贴+修改](草稿)
- 单片机开发之C语言编程基本规范
- c语言编程规范和范例
- C语言编程规范总结
- 华为C语言编程规范(6)—变量、结构
- 关于C语言编程书写规范的规则和建议
- 华为C语言编程规范—质量保证2