已阅读5页,还剩79页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
技术白皮书 C 语言 编码规则 版本 1 1日期 2007 7 29 上海 021 58380789北京 010 62131690 成都 028 86527582西安 029 88323529深圳 0755 83581788 前前 言言 技术白皮书 是由上海创景计算机系统有限公司翻译整理的高质量软件开发相关的 技术白皮书 鉴于目前国内相关行业实施高可靠性软件开发的现状 我们整理该白皮书的 目的是为了帮助软件开发人员在实际工作中更好的改进相关工作 我们希望通过我们的相关工作 辅助客户能够更好更快的实施高质量的软件开发 我 们的目标是为您提供一整套的高质量软件的开发和质量保证的解决方案 并通过我们优质 的服务保证该方案能够在相关单位按照符合单位现状的方式得到贯彻和实施 如果您有相关的问题或者建议请和我们联系 最后 衷心感谢多年来大家对上海创景计算机系统有限公司的关心和支持 1 目 录 1 过程名被重用 强制 1 2 文件中可执行格式化代码行超过 行 推荐 1 3 过程函数格式化代码行超过 行 推荐 2 4 函数指针的声明 强制 3 5 在非赋值表达式中出现了赋值操作符 强制 4 6 循环体没有用大括号括起来 推荐 5 7 then else 中的语句没有用大括号括起来 推荐 6 8 使用 goto 语句 强制 6 9 内嵌使用汇编代码 强制 7 10 过程参数超过 个 推荐 8 11 参数未使用类型声明 强制 9 12 实参与形参个数不匹配 强制 10 13 使用一些模糊的语句 如 推荐 11 14 函数未被调用 强制 12 15 返回类型为 VOID 的函数有 return 语句 强制 13 16 使用 或 操作符 推荐 13 17 使用 或者 操作符 推荐 14 18 在循环中使用 break 语句 推荐 15 19 圈复杂度大于 推荐 16 20 函数非结构化 推荐 17 21 未使用的函数参数 强制 18 22 代码中有多余变量 强制 19 23 存在 UR 数据流异常 强制 19 24 使用函数递归调用 强制 20 25 改变变量已被传递的值 强制 21 26 函数有多出口 强制 22 27 函数没有返回语句 强制 23 28 过程参数只有类型没有标识符 强制 24 29 使用不恰当的循环变量类型 强制 25 30 在函数参数表中使用省略号 强制 25 31 数组越界 强制 26 32 在 switch 语句中没有 default 语句 强制 27 33 对有符号类型进行移位操作 强制 28 34 禁止给无符号变量赋负值 强制 29 35 禁止对实数类型的变量做相等比较操作 强制 30 36 if 语句中没有 else 分支 推荐 31 37 switch 中的 case 没有以 break 终止 推荐 32 38 过程 函数的参数表为空 推荐 33 39 返回类型为 void 的过程出现在表达式中 强制 33 40 void 类型的变量作为参数进行传递 强制 34 41 函数中只有 return 语句没有返回值 强制 35 42 在头文件前有可执行代码 强制 36 2 43 枚举元素的初始化不完整 强制 36 44 用指针进行代数运算 推荐 37 45 字符类型没有标明是有符号还是无符号 强制 38 46 给变量赋的值与其类型不一致 强制 39 47 对指针变量使用强制类型转换 推荐 40 48 对其类型变量强制转换成指针变量 推荐 41 49 实参和形参类型不一致 强制 42 50 函数返回类型不一致 强制 43 51 函数与函数的原型的返回不一致 强制 44 52 函数和函数的原型的形参不一致 强制 45 53 结构体变量的初始化类型不一致 强制 45 54 变量在使用前没有被声明 强制 46 55 函数没有定义原型 强制 47 56 数组的下标不是整型 强制 48 57 逻辑上关联的表达式需要括号 推荐 48 58 使用指针做逻辑比较 推荐 49 59 使用混合方式运算 推荐 50 60 使用单行注释 推荐 51 61 布尔值首先与 0 进行比较 强制 52 62 数组没有边界限定 推荐 53 63 参数与全局变量同名 强制 54 64 由于设计原因导致某些代码不可执行 强制 54 65 结构声明不完整 推荐 55 66 在循环语句中有多个控制变量 推荐 56 67 使用 void 指针 推荐 57 68 或 不在单独的一行 推荐 58 69 之间的内容没有缩进两个空格 推荐 58 70 存在被零除错误 强制 59 71 变量名称只有大小写不同 强制 60 72 使用以下划线开始的变量名 强制 61 73 被包含文件内包含文件 推荐 61 74 for 循环语句使用空初始化表达式 推荐 62 75 for 循环语句使用空增量表达式 推荐 63 76 在头文件中定义函数 强制 64 77 存在不可达代码 强制 65 78 注释中可能包含代码 推荐 65 79 向没有打开的文件中写 强制 66 80 文件指针在退出时没有释放 强制 68 81 声明变量没有变量类型 强制 69 82 内存没有释放 强制 69 83 从释放的内存中读数据 强制 70 84 声明指针的指针 推荐 71 85 if 的嵌套深度大于 4 推荐 72 86 使用未初始化的指针 强制 73 3 87 枚举类型的变量的成员必须初始化为整型 推荐 74 88 数组的初始化必须完整 推荐 75 89 禁止两个布尔型变量进行比较 推荐 76 90 全局变量声明时没有初始化 强制 77 1 1 1 过程名被重用过程名被重用 强制强制 LDRA 1 1S MISRA 21 GJB 2 定义 定义 函数名与其他变量同名 说明 说明 C 语言允许在不同的程序段 基本块和命名域 内使用相同的 命名 但这是不安全的 因为它有可能混淆变量的活动作用域范围 举例 举例 示例示例 1 如下的例子中 foo 函数名和 main 函数的局部变量同名 容易造成混 淆 typedef unsigned int UINT32 void foo UINT32 p1 UINT32 x p1 void main void UINT32 foo 1 函数名与局部变量同名 建议 建议 为了提高代码的可读性和清晰性 不允许函数名被重用 2 2 文件中可执行格式化代码行超过文件中可执行格式化代码行超过 行行 推荐推荐 LDRA 3 3S GJB 4 2 定义 定义 源文件格式化后的可执行语句的行数不能超过 行 说明 说明 利用这条规则可以控制每个文件的代码量 门限值可以由用户 自定义 符号 指的是用户自定义的代码行数 推荐值是 2000 可通过 c cppen dat 文件配置 控制代码数量可以减小代码的复杂度 同时提高代码的可读性和可测试性 举例 举例 示例示例 1 格式化的可执行语句超过2000行的源程序 建议 建议 为减小代码的复杂度 提高代码的可读性和可测试性 建议用 户根据软件研制特点来确定适合本单位的代码数量门限值 3 3 过程函数格式化代码行超过过程函数格式化代码行超过 行行 推荐推荐 LDRA 4 4S GJB 5 定义 定义 过程或者函数格式化后的代码行数不能超过 行 说明 说明 利用这条规则可以控制每个函数的大小 符号 指的是用户自 定义的门限值 推荐值是 200 可通过 c cppen dat 文件配置 控制 函数大小可以减小函数的复杂度 同时提高代码的可读性以及可测 试性 3 举例 举例 示例示例1 如下的例子中 isHexDigit函数的格式化代码行数超过了默认的门限值 typedef unsigned char CHAR BOOL isHexDigit CHAR Hex BOOL isHexDigit CHAR Hex BOOL bResult bResult FALSE if Hex 0 Hex 1 Hex 2 Hex 3 Hex 4 Hex 5 Hex 6 Hex 7 Hex 8 Hex 9 Hex A Hex a Hex B Hex b Hex C Hex c Hex D Hex d Hex E Hex e Hex F Hex f bResult TRUE return bResult 此函数的格式化代码超过200行 建议 建议 为减小函数的复杂度 提高代码的可读性以及可测试性 建议 用户根据软件研制特点严格控制函数的大小 4 4 函数指针的声明函数指针的声明 强制强制 LDRA 6 6S GJB 7 定义 定义 程序中使用了函数指针 说明 说明 在某些情况下函数指针的使用被认为是危险的 必须严格控制 例如 指针具有欺骗性 而且会使控制流变得模糊 4 举例 举例 示例示例1 如下的例子中 声明了函数指针proc pointer映射到foo函数 typedef unsigned int UINT32 typedef unsigned short UINT16 void foo UINT32 p1 UINT16 p2 void main void void proc pointer UINT32 p1 UINT16 p2 foo 声明函数指针 proc pointer 1 1 建议 建议 由于函数指针具有危险性 建议用户不要使用函数指针 5 5 在非赋值表达式中出现了赋值操作符在非赋值表达式中出现了赋值操作符 强制强制 LDRA 9 9S MISR 33 GJB 10 定义 定义 在非赋值的表达式中使用了赋值操作符 说明 说明 赋值操作符 作为左值 而相等操作符 执行比较 非赋值表达式中出现赋值操作符可能是失误造成的 它有可能带来 不期望的副作用 举例 举例 示例示例1 如下的例子中 使用连等赋值操作将参数test的值赋给result和flag 要 仔细检查这种情况是否会带来副作用 BOOL foo BOOL test BOOL result flag 5 result flag test 使用连等赋值 引起非赋值表达式中出现了赋 值操作符 return result 建议 建议 由于在赋值表达式中出现赋值操作符可能会引起不期望的副作 用 所以要仔细检查程序中所有这些情况 6 6 循环体没有用大括号括起来循环体没有用大括号括起来 推荐推荐 LDRA 11 11S MISRA 59 GJB 11 12 定义 定义 循环体没有用大括号括起来 即使只有一条语句 说明 说明 出于代码维护性的考虑 循环体需要使用大括号 括起来 即 使循环体内只有一条语句 举例 举例 示例示例1 如下的例子中 循环体j 没有用大括号括起来 typedef signed int SINT32 SINT32 foo SINT32 p1 SINT32 j 10 SINT32 k 0 for k 0 k 0 i i 1 else i i 1 else中的语句没有用大括号括起来 return i 建议 建议 无论是then还是else 都建议使用大括号将其中的语句括起来 7 8 8 使用使用 gotogoto 语句语句 强制强制 LDRA 13 13S MISRA 56 GJB 14 定义 定义 程序中使用 goto 语句 说明 说明 goto 语句通常被认为是种很差的编程习惯 它的使用导致产生 非结构化的代码 增加了程序的复杂性 举例 举例 示例示例1 如下的例子中 出现了goto语句的使用 typedef signed int SINT32 void foo void SINT32 jump flag 0 start jump flag if jump flag 1 if i 0 break 循环中使用break语句 i i 1 建议 建议 循环中使用break语句一般是考虑程序的执行效率 建议用户在 代码结构化和程序执行效率间有个折中 不能过多地在循环中使用 break语句 也不是说绝对禁止在循环中使用break语句 1919 圈复杂度大于圈复杂度大于 推荐推荐 LDRA 35 1C 定义 定义 函数的圈复杂度不能大于预先定义的最大圈复杂度 说明 说明 圈复杂度是度量程序复杂性一个重要指标 圈复杂度越大就代 表程序越复杂 因此就越难理解和维护 规则用来限制函数的大小 符号 指的是用户自定义的门限值 推荐值是 10 或者是基于所 在单位的现有软件的圈复杂度的情况来定门限 比如取现有软件模 块中圈复杂度较小的 80 做为门限 举例 举例 17 示例示例 1 圈复杂度大于 10 的函数示例 建议 建议 考虑到代码的清晰性和维护性 函数的圈复杂度不宜过大 各单 位应结合软件研制特点确定适合自己的圈复杂度最大值 20 函数非结构化函数非结构化 推荐推荐 LDRA 38 4C 定义 定义 函数是非结构化的函数 说明 说明 C 语言是结构化的语言 按照规范的程序设计方法编写的代码 应该是结构化的 结构化的代码便于理解和维护 但是 C 语言中的 某些用法 比如 for while switch 使用不当就很容易造成非结构 化的程序 导致程序的清晰性和可维护性降低 规则按照结构化化 简的方法识别程序内所有的非结构化函数 举例 举例 示例示例 1 如下的例子中 for 循环中使用了 break 语句 导致 foo 函数非结构化 typedef unsigned int UINT32 void foo void 函数是非结构化的 UINT32 i 0 for i 0 i 10 i if i 5 18 break 建议 建议 在现阶段不可能完全避免非结构化的程序设计 由于非结构化 造成的代码清晰性和维护性降低 对于非结构化的函数要给予更多 的关注 在代码分析和单元测试阶段要更充分地验证这些函数以保 证它们的可靠性 21 未使用的函数参数未使用的函数参数 强制强制 LDRA 40 1D 定义 定义 参数在函数的任何路径和计算结果中都没有使用到 说明 说明 函数的任何路径和计算结果都没有使用到的参数被认为是多余 的 这是概要设计上的失误 可以简单的删除 举例 举例 示例示例 1 如下的例子中 在形参 p2 在函数 foo 的任何路径下都没有使用到 并 且返回值也与它无关 typedef unsigned int UINT32 UINT32 foo UINT32 p1 UINT32 p2 UINT32 foo UINT32 p1 UINT32 p2 UINT32 v1 v1 p1 v1 return v1 参数p2在函数内没有使用到 19 建议 建议 函数内不使用的参数应该被删除 以提高代码的清晰性 22 代码中有多余变量代码中有多余变量 强制强制 LDRA 43 4D GJB 144 定义 定义 分析的代码中存在声明的变量但是从来没有使用过 说明 说明 代码中未使用的变量会浪费的额外的数据空间 可以简单的删 除 举例 举例 示例示例 1 如下的例子中 变量 v2 在代码中没有被使用 可以删除 typedef unsigned int UINT32 UINT32 foo void UINT32 v1 v2 v1 0 return v1 代码未使用变量v2 建议 建议 为提高代码效率 降低代码冗余性 代码内未使用的变量应该 删除 20 23 存在存在 UR 数据流异常数据流异常 强制强制 LDRA 44 5D MISRA 30 GJB 139 定义 定义 变量在函数的某些路径上未赋初值就被引用 说明 说明 变量未赋初值就被引用是很危险的 编译器会对变量进行默认 的初始化赋值 因此这个变量值是不确定的 从而有可能造成代码 运行时的异常 举例 举例 示例示例 1 如下的例子中 变量 v2 未赋初值就被引用 假如 v2 的值为 0 就引起 除 0 的异常 typedef unsigned int UINT32 UINT32 foo void UINT32 v1 v2 v1 1000 v2 变量v2未赋初值就被引用 return v1 建议 建议 建议用户在声明变量时就对其进行初始化 从而可以避免对它 访问时造成的UR异常 24 使用函数递归调用使用函数递归调用 强制强制 LDRA 45 6D MISRA 70 定义 定义 21 程序中存在直接或者间接调用自己的函数 说明 说明 函数递归调用通常是被禁止的 因为它可能会引起程序运行时 的空间溢出 而且如果程序设计人员没有良好地设计调用结构 很 容易产生无限的递归调用 举例 举例 示例示例 1 如下的例子中 函数 foo 存在递归调用 如果不仔细考虑递归的结束判 断条件 很有可能造成无限的嵌套 typedef unsigned int UINT32 UINT32 foo UINT32 para UINT32 result UINT32 value if para 1 value pa a value result foo value para 使用递归调用 else result 1 return result 建议 建议 为避免程序运行时出现异常 建议将递归函数调用改用其他的 程序设计方法实现 25 改变变量已被传递的值改变变量已被传递的值 强制强制 LDRA 53 14D DERA 152 22 定义 定义 在函数中对传递值的形参重新赋值 说明 说明 C 语言中允许对传递值的形式参数再次赋值 但这是个错误 因为这样参数传值的作用就消失了 举例 举例 示例示例 1 如下的例子中 在函数 foo 内对传值的形参 par1 再次赋值 导致形参 的传值作用消失 typedef unsigned int UINT32 void foo UINT32 par1 UINT32 par2 if par2 1 par1 0 对传值的形参par1赋值 else par1 1 对传值的形参par1赋值 建议 建议 函数中对传值的形参进行赋值屏蔽了参数的作用 是设计上的 错误 应该从设计的角度考虑解决问题 26 函数有多出口函数有多出口 强制强制 LDRA 58 7C MISRA 82 定义 定义 函数存在多个返回出口 23 说明 说明 结构化程序设计要求函数只有一个入口和一个出口 函数的出口 位于函数的结尾返回语句之处 多出口使函数变得非结构化 降低 了代码的清晰性和可维护性 举例 举例 示例示例 1 如下的例子中 函数 complexity 存在两个出口 typedef unsigned int UINT32 UINT32 complexity BOOL c1 BOOL c2 BOOL c3 BOOL c4 if c1 if c3 return 1 if c2 if c4 return 2 函数存在多个出口 建议 建议 对于多出口的函数 建议用户通过添加返回变量的程序设计方 法修改为单出口的函数 27 函数没有返回语句函数没有返回语句 强制强制 LDRA 60 36S MISRA 75 GJB 35 定义 定义 有返回类型的函数却没有返回语句 说明 说明 有返回类型的函数必须有返回语句 假如没有返回语句 函数调 24 用时通常会返回一个堆栈栈顶的随机值 某些编译忽略了这类错误 的检查 因此有可能会引起程序运行中出现异常 举例 举例 示例示例 1 如下的例子中 函数 foo 的返回类型为无符号整型 却没有返回语句 typedef unsigned int UINT32 UINT32 foo UINT32 p1 UINT32 y p1 函数无返回语句 建议 建议 为避免程序运行时刻的异常 声明有返回类型的函数必须要有 返回语句 28 过程参数只有类型没有标识符过程参数只有类型没有标识符 强制强制 LDRA 61 37S MISRA 73 GJB 36 定义 定义 函数的形式参数只有类型而没有标识符 说明 说明 某些编译器允许函数的形式参数只有类型而没有标识符 但是这 样参数并不能真正使用 从而造成产生的程序存在隐患 举例 举例 示例示例 1 如下的例子中函数 foo 的第二个形参只有类型没有标识符 typedef unsigned int UINT32 struct s type b UINT32 xs void foo UINT32 p1 struct s type b 函数形参只有类型无标志符 25 建议 建议 由于不同的编译器的适应性不同 建议函数的形式参数必须同 时具有类型和标识符 29 使用不恰当的循环变量类型使用不恰当的循环变量类型 强制强制 LDRA 63 39S MISRA 65 GJB 37 定义 定义 许多数据类型不适合作为循环的控制变量 尤其是浮点数 说明 说明 浮点类型的变量不适合作为循环控制变量 因为浮点数存在精 度上的误差 有可能引起循环的执行数目异常 举例 举例 示例示例 1 如下的例子中 函数 foo 循环体控制变量 f 是浮点类型的 typedef float FLOAT32 void foo void FLOAT32 f 0 0 for f 0 0 f 10 0 f f 1 0 循环控制变量是浮点类型的 建议 建议 为避免循环执行出现异常 建议只使用整型变量作为循环的控 制变量 26 30 在函数参数表中使用省略号在函数参数表中使用省略号 强制强制 LDRA 65 41S MISRA 69 GJB 39 定义 定义 函数使用省略号描述参数列表 说明 说明 某些编译器允许函数的参数列表使用省略号 表示函数可以接 受变化数目的参数 并且还阻止了任何的检查机制 比如参数类型 检查 参数个数检查等 这样就导致了程序设计的不确定性 极有 可能引发程序运行异常 举例 举例 示例示例 1 如下的例子中 函数 foo 的参数列表使用省略号 include typedef unsigned int UINT32 typedef unsigned char UCHAR UINT32 foo UCHAR p1 参数列表使用省略号 va list ap UCHAR t va start ap p1 t va arg ap UCHAR va end ap return 1 void dummy void foo xyz s 函数调用时可以引用任意数目的变量 建议 建议 27 建议在概要设计阶段就要明确函数接口 确定函数参数的个数 和类型 禁止采用省略号来描述参数列表 3131 数组越界数组越界 强制强制 LDRA 71 47S MISRA 4 GJB 45 定义 定义 数组元素的下标不在数组的定义范围内 说明 说明 这条规则强制用于有确定范围定义的数组 对不在数组声明范 围内的数组元素赋值会引起数组的静态越界 举例 举例 示例示例 1 如下的例子中 数组 a 含有 4 个元素 a 4 不在数组定义的范围之内 typedef unsigned int UINT32 void foo void int a 4 0 0 0 0 a 4 5 数组静态越界 建议 建议 对于有确定的范围定义的数组 用户需要额外注意其数组元素 的引用 以免发生数组静态越界的情况 3232 在在 switchswitch 语句中没有语句中没有 defaultdefault 语句语句 强制强制 LDRA 72 48S MISRA 62 GJB 46 145 28 定义 定义 switch case 的控制结构中 没有考虑默认的 default 分支的情况 说明 说明 假如 switch 结构中没有考虑 default 分支 并且所有的 case 条件 都不满足 那么控制流会转向执行未知的下一条语句 在某种程度 上存在着安全隐患 举例 举例 示例示例 1 如下的例子中如果 p 的值为 2 程序会执行一条未知的语句然后返回 这有可能会引起程序异常 typedef unsigned int UINT32 void proc UINT32 p UINT32 i 0 UINT32 j 0 switch p case 0 j 0 break case 1 j i break switch结构中没有default分支 建议 建议 为了预防程序异常的情况出现 建议用户在 switch case 的结构 中必须考虑 default 分支 29 3333 对有符号类型进行移位操作对有符号类型进行移位操作 强制强制 LDRA 74 50S MISRA 37 GJB 48 定义 定义 对有符号类型的变量进行移位操作 说明 说明 对有符号的类型的变量进行移位操作会带来严重的影响 比如 可能会导致产生不期望的值 举例 举例 示例示例 1 如下的例子中 对有符号类型变量 b 进行移位操作 最终 b 的结果还 是 1 并不是期望的结果 typedef signed int SINT32 void foo void SINT32 b 1 b 1 对符号类型变量b进行移位操作 建议 建议 建议用户谨慎对待有符号类型变量的操作 尽量避免对有符号 类型变量进行移位操作 3434 禁止给无符号变量赋负值禁止给无符号变量赋负值 强制强制 LDRA 76 52S MISRA 39 GJB 50 定义 定义 不允许对无符号类型的变量赋负值 说明 说明 30 对无符号类型的变量赋负值是没有意义的 最终输出的结果会 是一个不期望的正值 举例 举例 示例示例 1 如下的例子中 对无符号类型变量 y 赋值 1 最终 y 的值是不期望的正 值 typedef unsigned int UINT32 void foo void UINT32 x 1 UINT32 y 2 y x 对无符号类型变量y赋负值 建议 建议 运算中隐含的类型转换可能会对无符号变量赋负值 从而引起不 正确的结果 因此用户必须仔细检查这种情况是否会出现 3535 禁止对实数类型的变量做相等比较操作禁止对实数类型的变量做相等比较操作 强制强制 LDRA 80 56S MISRA 50 GJB54 定义 定义 不允许对实数类型变量做相等的比较判断 包括 说明 说明 作为实数类型的变量 在计算机内部都有一定的精度 所以两 个实型变量的值不可能完全相等 举例 举例 示例示例 1 如下的例子中 对实型变量 f1 和 f2 做相等比较 很明显这两个变量不 可能完全相等 31 typedef float FLOAT32 void foo void FLOAT32 fl f2 fl 1 01 f2 1 01 if fl f2 实型变量做相等比较 else 建议 建议 由于两个实型变量的值不可能完全相等 所以建议用户对两个 实数型变量一般进行临界值的比较 比如 If x y threshold 3636 ifif 语句中没有语句中没有 elseelse 分支分支 推荐推荐 LDRA 83 59S MISRA 60 GJB 57 定义 定义 if 语句应该有对应的 else 语句与之匹配 说明 说明 if 语句中没有 else 分支 可能是 else 分支为空 也有可能是程 序员设计上的失误 原则上 if 语句应该有 else 与之对应 举例 举例 示例示例 1 如下的例子中 if 语句没有 else 分支 很显然程序中没有处理 x 值不 32 是 2 也不是 3 的情况 这是设计上的缺陷 typedef unsigned int UINT32 void foo void UINT32 x 2 if x 2 else if x 3 if语句中缺少else分支 建议 建议 即使 else 语句为空 也建议用户在 if 语句中不能丢失 else 分 支 以避免产生晦涩的代码和设计上的缺陷 3737 switchswitch 中的中的 casecase 没有以没有以 breakbreak 终止终止 推荐推荐 LDRA 86 62S MISRA 61 GJB 60 定义 定义 switch 结构中的 case 分支没有用 break 语句来终止 说明 说明 switch case 控制结构中的错误很有可能从一个 case 直接跳转到 另外一个 case 引起的 可以用 break 语句来避免这种控制流跳转 举例 举例 示例示例 1 如下的例子中 假如 p1 的值为 0 那么控制流将会从 case 0 直接跳转 到 case 1 有可能引起程序异常 typedef unsigned int UINT32 void foo UINT32 p1 33 UINT32 i 0 j 0 switch p1 case 0 j 0 switch语句中的case语句没有以break终止 case 1 j i break default i j 1 建议 建议 建议用户尽量在 swtich 结构的 case 分支中使用 break 语句 确 保每次只能访问 switch 结构中的一个 case 语句 3838 过程过程 函数的参数表为空函数的参数表为空 推荐推荐 LDRA 85 63S MISRA 79 GJB 61 定义 定义 过程或者函数参数列表为空 说明 说明 假如过程或者函数没有参数 推荐使用 void foo void 而不是 void foo 来声明函数 这样才能表明是程序员有意地设计为函数没 有参数 而不是失误 举例 举例 示例示例 1 如下的例子中 foo 函数使用空参数列表 void foo 函数使用空参数列表 34 建议 建议 建议用户在声明没有参数的函数时使用void描述函数参数列表 3939 返回类型为返回类型为 voidvoid 的过程出现在表达式中的过程出现在表达式中 强制强制 LDRA 86 64S MISRA 79 GJB 62 定义 定义 返回类型为 void 的函数出现在表达式中 说明 说明 程序中使用 void 作为返回类型的函数出现在表达式中是非常危 险的 某些编译器不会检查这类错误 默认为 void 类型的函数分配 一个随机的返回值 举例 举例 示例示例 1 如下的例子中 void 类型的函数 foo 赋给了 x 变量 导致 x 的值不确 定 void foo void void main void CHAR x x CHAR foo void类型的函数赋给变量x 建议 建议 不允许用户在表达式中使用 void 返回类型的函数 这是非常危 险的 35 4040 voidvoid 类型的变量作为参数进行传递类型的变量作为参数进行传递 强制强制 LDRA 87 65S MISRA 80 GJB 63 定义 定义 void 类型的变量作为函数的参数来传递值 说明 说明 传递 void 类型的参数会导致传值的结果不确定 某些编译器不 会检查这类错误 有可能会带来不期望的影响 举例 举例 示例示例 1 如下的例子中 使用 void 类型的变量 ptr 进行 void para func 函数的参 数确定 结果不确定 void void para func void P1 void main void void ptr void para func ptr 使用void类型的变量进行参数传递 建议 建议 不允许用户使用 void 类型的变量进行参数传递 4141 函数中只有函数中只有 returnreturn 语句没有返回值语句没有返回值 强制强制 LDRA 90 66S MISRA 83 GJB 64 定义 定义 36 有返回类型的函数只有 return 语句却没有指定返回值 说明 说明 假如有返回类型的函数只有 return 语句却没有指定返回值 那 么此返回值为随机值 有可能引起程序异常 举例 举例 示例示例 1 如下的例子中 返回类型为无符号整型的函数 foo 只有 return 语句 却 不指定返回值 导致此返回值是个随机值 typedef unsigned int UINT32 UINT32 foo UINT32 p return 函数只有返回语句却没有返回值 建议 建议 建议在有返回类型的函数中必须指定函数的返回值 4242 在头文件前有可执行代码在头文件前有可执行代码 强制强制 LDRA 99 75S MISRA 87 GJB 73 定义 定义 头文件前还存在可执行代码 说明 说明 为提高代码的清晰性 要求头文件仅仅出现在文件的开始 所 有可执行代码前 举例 举例 示例示例 1 如下的例子中 c standard h 头文件前有可执行语句 导致代码结构不 清晰 void foo void 37 include c standards h 头文件前存在可执行代码 建议 建议 建议用户将包含的头文件放在文件的开始 所有可执行语句的 前面 4343 枚举元素的初始化不完整枚举元素的初始化不完整 强制强制 LDRA 109 85S MISRA 32 GJB 83 定义 定义 枚举元素只初始化了部分元素 初始化不完整 说明 说明 枚举类型的初始化必须明确 有两种形式的初始化是安全的 一种是把所有元素都初始化 另一种是只初始化第一个元素 另外 枚举类型的所有元素都不初始化也是安全的 举例 举例 示例示例 1 如下的例子中 枚举类型 E type 只对第二个元素 num2 进行初始化 导致其他元素的值不确定 是不安全的 void foo void enum E type num1 num2 2 num3 枚举元素初始化不完整 建议 建议 假如要对枚举元素进行初始化 建议用户要么把所有元素都初 始化 要么只初始化第一个元素 38 4444 用指针进行代数运算用指针进行代数运算 推荐推荐 LDRA 111 87S MISRA101 GJB 85 定义 定义 在代码运算中使用指针变量作为操作数 说明 说明 由于无法确保指针的运算结果是个有效的地址 所以对指针进 行代数运算是不安全的 举例 举例 示例示例 1 如下的例子中 将数组 array 的首地址赋给指针变量 p1 ptr 然后对其 进行运算 结果指向数组 array 中第 9 个元素的地址 但数组 array 只有 5 个元 素 这个地址并不是个有效地址 typedef unsigned it UINT32 void foo void UINT32 w UINT32 array 5 UINT32 p1 ptr p1 ptr array w p1 ptr 8 对指针变量进行代码运算 建议 建议 建议用户尽量避免对指针进行代数运算 假如存在这样的操作 要仔细核查指针运算后的结果是否有效 39 4545 字符类型没有标明是有符号还是无符号字符类型没有标明是有符号还是无符号 强制强制 LDRA 113 89S MISRA 14 GJB 87 定义 定义 声明字符类型的变量需要确定是有符号的还是无符号的 说明 说明 编译器中没有 char 型的概念 会默认地将 char 型变量转换为 unsigned char 或 signed char 不同编译器的默认设置是不一样的 考 虑到代码的可靠性和可移植性 必须确定字符变量是有符号的还是 无符号的 举例 举例 示例示例 1 如下的例子中 字符型变量 c 没有标明是有符号的还是无符号的 typedef char CHAR void foo void CHAR c c 字符型变量c没有标明是有符号的还是无符号的 建议 建议 建议用户在声明字符型变量必须确定是有符号的还是无符号的 4646 给变量赋的值与其类型不一致给变量赋的值与其类型不一致 强制强制 LDRA 117 93S MISRA 18 48 GJB 90 定义 定义 对变量赋的值与变量的类型不一致 40 说明 说明 对变量赋的值与其类型不一致会隐藏强制类型转换的操作 而 不同的编译器默认的强制类型转换是不同的 可能导致赋的值不是 期望的结果 举例举例 示例示例 1 如下的例子中 对无符号整型变量 d 赋值 2 0 隐含了将 2 0 转换为无 符号整型的强制类型转换 typedef unsigned int UINT32 void STATIC 93 void UINT32 d d 2 0 对变量赋值与类型不一致 建议 建议 不允许用户对变量赋的值与变量类型不一致 必要时需要显式 的进行强制类型转换 4747 对指针变量使用强制类型转换对指针变量使用强制类型转换 推荐推荐 LDRA 118 94S MISRA 45 48 GJB 91 定义 定义 将指针类型的变量强制转换为其他类型的变量 说明 说明 强制转换指针类型的变量为其他类型的变量是非常危险的 其 产生的结果是否正确不可预知 可能会产生不确定或者限定执行的 行为 内存队列的某些方面是限定执行的 在 C 程序中有几种特 41 殊情况下强制转换指针类型是允许的 如 例 2 举例 举例 示例示例 1 如下的例子中 指针变量 p1 ptr 强制转化为无符号短整型并且赋给变 量 v v 的值不能确定 typedef unsigned int UINT32 typedef unsigned short UINT16 void foo UINT32 p1 ptr UINT16 v v UINT16 p1 ptr 指针变量强制转换为其他类型 示例示例2 用C 实现的底层的内存管理程序中 如果一个对象的类型确定为T时 允许将Void 强制转换为T 建议 建议 由于指针变量强制类型转换后的结果不可预知 所以建议用户 尽量避免对指针变量进行强制类型转换 4848 对其类型变量强制转换成指针变量对其类型变量强制转换成指针变量 推荐推荐 LDRA118 95S MISRA 45 48 GJB 91 定义 定义 将其他类型的变量强制转换成指针变量 说明 说明 其他类型变量强制转换成指针变量时需要谨慎对待 因为除了 通过取地址的操作产生指针外都是非常危险 在 C 程序中有几种 特殊情况下强制转换为指针类型是允许的 如 例 2 举例 举例 42 示例示例 1 如下的例子中 将无符号短整型的变量 s 强制转换无符号整型的指针 变量 存在一定的危险性 typedef unsigned int UINT32 typedef unsigned short UINT16 void foo void UINT16 s 0 UINT32 p1 ptr p1 ptr UINT32 s 将其他类型的变量强制转换为指针变量 示例示例 2 字面的 如 硬件地址值 转换为指针是允许的 Device register input reinterpret cast 0XFFA 建议 建议 由于将其他类型的变量强制转换成指针变量存在一定的危险性 所以建议用户尽量避免对其他类型变量强制转换成指针变量 4949 实参和形参类型不一致实参和形参类型不一致 强制强制 LDRA 122 98S MISRA77 GJB 95 定义 定义 函数的实参和形参类型不一致 说明 说明 形参指的是函数原型中的参数 实参指的是出现在函数调用中 的参数 某些编译器会忽略函数的实参和形参不一致这种错误 导 致产生的代码存在隐患 举例 举例 示例示例 1 如下的例子中 函数 foo 的实参类型为无符号短整型 而形参的类型为 无符号整型 由于类型不一致编译器在赋值的过程中有可能产生不期望的结果 43 typedef unsigned short UINT16 typedef unsigned int UINT132 void foo UINT16 p1 UINT16 p2 void main UINT32 p1 UINT16 p2 foo p1 p2 实参和形参类型不一致 建议 建议 由于编译器对代码的约束能力不同 为避免生成的代码存在隐 患 建议实参和形参之间传值时必须要保证类型的一致 否则可能 会产生不正确的结果 5050 函数返回类型不一致函数返回类型不一致 强制强制 LDRA 125 101S MISRA 83 GJB 98 定义 定义 函数返回语句中返回值的类型与函数定义的返回类型不一致 说明 说明 函数返回语句中返回值的类型和函数定义的返回值类型不一致 时 编译器会对返回值进行默认的强制类型转换 然后返回该值 这有可能带来不可预料的结果 举例 举例 示例示例 1 如下的例子中 函数的返回类型是无符号整型 而第一个 case 分支中 返回值类型却不同 是有符号整型 有可能造成函数返回的结果出现异常 typedef unsigned int UINT32 44 UINT32 foo UINT32 par switch par case 0 return 1 函数返回值的类型与函数定义的类型不一致 break case 1 return 2 break case 2 return 5 break default break 建议 建议 为了避免函数的返回值出现异常 建议函数返回语句中返回值 的类型与函数定义的返回类型始终保持一致 5151 函数与函数的原型的返回不一致函数与函数的原型的返回不一致强制强制 LDRA 126 102S MISRA 72 GJB 99 定义 定义 函数定义中的返回类型与函数原型中的返回类型不一致 说明 说明 通常表现为函数定义中的返回类型与函数原型中的返回类型不 一致 这样会导致产生的代码清晰性降低 举例 举例 示例示例 1 如下的例子中 函数 foo 原型声明的返回类型是无符号整型 而函数 定义时的返回类型为无符号短整型 45 typedef unsigned int UINT32 typedef unsigned short SINT32 UINT32 foo UINT32 p SINT32 foo UINT32 p 函数的返回类型与函数原型的返回类型不一致 SINT32 result 0 return result 建议 建议 由于不同的编译器对代码的约束能力不同 为避免生成的代码 清晰性降低 建议函数定义的返回类型要和函数原型的返回类型始 终保持一致 5252 函数和函数的原型的形参不一致函数和函数的原型的形参不一致 强制强制 LDRA 127 103S MISRA 72 GJB 100 定义 定义 函数定义时的形参与函数原型声明中的形参不一致 说明 说明 通常表现为函数定义中的参数类型与函数原型中的参数类型不 一致 某些编译器会忽略这种错误 从而降低了代码的清晰性 举例 举例 示例示例 1 如下的例子中 函数 foo 原型中的形参为 float 类型 而函数定义中 的参数类型为无符号整型 导致代码的清晰性降低 typedef unsigned int UINT32 typedef float FLOAT32 BOOL foo FLOAT32 up 46 BOOL foo UINT32 up 函数原型与函数定义的形参不一致 BOOL ret FALSE return ret 建议 建议 为了产生更清晰易读的代码 建议在函数原型声明和函数定义时 的参数类型要保持一致 5353 结构体变量的初始化类型不一致结构体变量的初始化类型不一致 强制强制 LDRA 128 104S MISRA 29 GJB 101 定义 定义 结构体变量的初始化与结构体定义的类型不一致 说明 说明 假如结构体初始化值与结构体定义的类型不一致 那么编译器 一般会进行强制类型转换 有可能会得到错误的结果 举例 举例 示例示例 1 如下的例子中 结构变量 sta 初始化时第一个元素的赋值与其类型不一
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 燃气管道运行风险评估与管控方案
- 银行债券笔试题库及答案
- Unit3-Warming-Up-and-Reading-夯实基础训练
- 建筑外墙外保温修缮用界面处理剂
- TACEF-便携式活性炭四氯化碳(CTC)值检测仪技术要求及检测规范那你咋没
- 福建省厦门市同安区2026届九年级上学期期中考试物理试卷(含答案)
- 建筑项目工人健康保障方案
- 城市雨水管网整治方案
- 2025年安全月安全知识竞赛题库及答案
- 江苏省淮安市高中校协作体2025-2026学年高二上学期11月期中考试政治试题(合格考)
- 2025云南楚雄州元谋县国有资产投资管理有限公司招聘工作人员18人笔试历年参考题库附带答案详解
- 德育课程开发与实施评价方案
- 2025年中国匹克球设备行业市场全景分析及前景机遇研判报告
- 2025年小学数学课程标准试题及答案
- 国家级教改课题申报书
- 排水沟工程施工合同协议书6篇
- 2025四川高考政治试题解读及2026备考策略指导课件
- 幕墙创优工程汇报材料
- 矿区生态修复后期管护方案
- 2025至2030中国船用阀和执行器行业产业运行态势及投资规划深度研究报告
- 厂房电力系统安全评估报告
评论
0/150
提交评论