QAC 检查标准( MISRA 标准),MISRA ( The Motor Industry Software Reliability Association (4E4fE) TX 个跨国汽车工业协会,其成员包括了大部分欧美汽车生产商。其核心使命是为汽车工业提供服务和协助,帮助厂方开发安全的、高可靠性的嵌入式软件。这个组织最出名的成果是所谓的 MISRA C Coding Standard ,这一标准中包括了127条 C 语言编码标准,通常认为,如果能够完全遵守这些标准,则你的 C 代码是易读、可靠、可移植和易于维护的。
以下是对其编程规则的总结可做参考。
1. 遵循ANSI C89:确保代码仅使用C89标准,不包含编译器特定扩展。
2. 汇编语言封装:任何汇编代码必须封装在仅包含汇编指令的C函数中。
3. 避免三元操作符:不使用条件运算符 `?:`。
4. 删除注释掉的代码:代码中不应有废弃的、被注释掉的代码段。
5. 标识符长度限制:所有标识符(变量、函数等名字)长度不得超过31个字符。
6. 命名空间唯一性:不同作用域内的变量名应保持唯一,避免重名混淆。
7. 自定义数据类型:使用明确指定大小的数据类型代替基本类型,如 `INT32`, `FLOAT32`。
8. 字符类型明确:`char` 必须明确声明为 `signed char` 或 `unsigned char`。
9. 数字常量后缀:数字常量需带有类型指示后缀,如 `51L`, `42U`, `34.12F`。
10. 禁止八进制数:避免使用八进制常量,因其可能导致误解。
11. 避免局部遮盖全局:编译单元内,对象不应与外部作用域中的标识符同名。
12. 静态声明:文件作用域对象推荐声明为 `static`。
13. 链接一致性:同一标识符在同一编译单元内不应同时具备内部和外部链接。
14. 单一声明:具有外部链接的标识符仅声明一次。
15. 外部对象声明:外部对象不应在多个文件中重复声明。
16. 禁用register关键字:不使用 `register` 存储类说明符。
17. 自动对象初始化:栈上创建的对象(自动变量)在使用前必须初始化。
18. 逻辑运算符右侧副作用:`&&` 和 `||` 运算符的右侧表达式不应有副作用。
19. 布尔表达式中无赋值:条件判断中避免赋值操作,如 `if(!(fp = fopen("fname","r"))) {...}`。
20. 有符号数位操作:禁止对有符号数进行位运算,使用无符号类型时可加 `UL` 后缀。
21. 一元负号与有符号表达式:避免对有副作用的表达式使用一元负号。
22. sizeof与副作用:禁止 `sizeof` 应用于有副作用的表达式。
23. 限制逗号表达式:除循环控制外,避免使用逗号表达式。
24. 避免冗余转换:如无需转换,不要进行显式类型转换。
25. 指针类型转换限制:禁止任意类型与指针间的直接强制类型转换。
26. 测试值为零:明确测试变量是否等于零,而非使用其他比较。
27. 禁止浮点数直接比较:避免直接比较浮点数的相等或不等。
28. 去除无用代码:删除不会被执行的代码。
29. 语句应有副作用:每条执行语句应具有实际效果。
30. 限制使用标签和goto:除 `switch` 外,避免使用标签和 `goto`。
31. 禁止continue使用:不使用 `continue` 跳过循环部分。
32. 限制break使用:除 `switch` 外,避免使用 `break`。
33. 块语句使用大括号:保证控制结构体如 `if`、`while` 使用大括号包围。
34. if-else 结构完整:if-else-if 结构最后应有默认的 `else` 分支。
35. 循环计数器不变:循环体内不改变循环计数器的值。
36. 禁止递归:不允许直接或间接的函数递归调用。
37. 单出口函数:每个函数只有一个返回点。
38. 检测函数错误:调用可能返回错误的函数后,必须检查其返回值。
39. 避免使用#undef:不使用 `#undef` 来取消宏定义。
40. 宏参数传递限制:不要将宏作为另一个宏的参数。
41. 宏定义中的#和##:一个宏定义中 `#` 或 `##` 符号只应出现一次。
42. 禁止指针运算:使用数组索引代替指针运算。
43. 限制指针级别:最多使用二级指针。
44. 非const指针:不使用指向非const数据的指针。
45. 栈对象地址传递:不可将栈对象地址赋给超出作用域的对象。
46. 禁止动态内存分配:不使用 `malloc`, `calloc`, `realloc`。
47. 忽略errno:不使用 `errno` 错误变量。
48. 禁止offsetof:不使用 `offsetof` 宏。
49. 禁用locale.h:不包含 `<locale.h>`。
50. 禁用setjmp/longjmp:不使用 `setjmp` 和 `longjmp`。
51. 禁用signal.h:不使用 `<signal.h>`。
52. 禁用stdio.h:不使用 `<stdio.h>`,避免 `printf`, `scanf`。
53. 禁用atoi/atof/atol:使用更安全的 `strtol`, `strtod` 替代。
54. 禁用abort/exit/getenv:不使用 `abort`, `exit`, `getenv`。
55. 禁用time.h:不使用 `<time.h>`。
这套规则通过限制某些编程习惯和语法的使用,来减少潜在的错误和提升代码的可维护性,特别适合于安全性要求极高的嵌入式系统开发。