MISRS C:2004编程规范:——重要知识点

MISRS C:2004编程规范:——重要知识点
MISRA C:2004建议程序中的代码段不要被“注释掉”。注释掉代码段很容易产生嵌套注释,所以应该用条件编译指令(如 #if 0…#endif)使相应的代码段失效。
MISRA C:2004要求所有#pragma指令(预处理指令)的使用应该文档化并给予解释。#pragma指令是由C标准规定的方法,用于给编译器提供额外的信息,提高了C源程序对编译器的可移植性。
MISRA C:2004明确指出++和--运算符不得和其他运算符混合使用。逻辑运算符&& 和 || 的右操作数不得带有副作用。
1、数据类型相关的编码风格
(1)必须使用typedef显示标识出各数据。不要直接使用char,int,float等基本数据类型。而应使用“特定长度”的typedef,显示的指出数据类型的大小和符号。
(2)不得使用八进制常数(0除外)或八进制转义符。(八进制常数需要在最高位加数字0,容易造成误解)
(3)简单的char类型只可用于字符类型。
(4)signed char 和 unsigned char 类型只可用于数字值。
(5)位域只能被定义为unsigned int和signed int类型。
(6)unsigned int 类型的位域至少应该为2位长度。
2、数据类型的转换
(1)对无符号字符型或无符号短整型进行~和<<位运算后,其结果应立即强制转换成操作数的基本类型。
(2)整型表达式中不允许出现以下情况的隐式数据类型转换:
  • 无符号整型和有符号整型的转换
  • 整型和浮点型的转换
  • 复杂表达式的数据类型转换
  • 从宽类型到窄类型的转换
  • 函数返回表达式类型转换
  • 函数实参类型转换
(3)浮点数表达式中不允许以下情况出现隐式数据类型转换:
  • 不同位数的浮点类型转换
  • 复杂表达式的数据类型转换
  • 函数实参类型转换
  • 函数返回表达式的类型转换
这两个规则广泛遵循以下原则:
  1. 有符号和无符号之间没有隐式转换
  2. 整型和浮点类型之间没有隐式转换
  3. 没有从宽到窄的隐式转换
  4. 函数参数没有隐式转换
  5. 函数的返回表达式没有隐式转换
  6. 复杂表达式没有(不同类型)隐式转换
(4)整型复杂表达式的值只能强制转换到更窄的类型且表达式的基本类型具有相同的符号。
(5)浮点类型复杂表达式的值只能强制转换到更窄的浮点数类型。
(6)后缀“U”应该用在所有unsigned 类型的常量上。
3、初始化规范
(1)自动变量在使用前都应被赋值。
(2)应该使用大括号以指示和匹配数组和结构的非零初始化构造。
(3)在枚举列表中,“=”不能显式用于除首元素之外的元素,除非所有元素都是显式初始化的。
4、指针规范
1)指针的类型转换
(1)指向不同数据类型的指针之间不能相互转换。
(2)指针转换过程中不允许丢失指针的const volatile属性。
2)指针和数组的运算
(1)只有指向数组的指针才允许进行算数计算。(仅限于指针加减某个整数)
(2)只有指向同一个数组的两个指针才允许相减。
(3)只有指向同一个数组的两个指针才允许用>,>=,<,<=等关系运算符进行比较。
(4)只允许用数组索引执行指针运算。
3)指针的有效性
(1)不允许将栈对象的地址传给外部作用域的对象。
5、表达式规范
C语言标准规定的只是运算符的结合顺序,而对于二元运算符两边的操作数的求值顺序则未定义。意味着结果可能取决于编译器的特性(从左向右解析还是从右向左解析)。
(1)表达式的值在标准所允许的任何运算次序下都应该是相同的。什么时候不同呢?(当表达式中的操作数(表达式)能影响某个共享变量,而这个共享变量又有可能导致其余操作数的值发生变化时,就需要对求值顺序进行分析。
(2)应该减少表达式对C语言运算符优先级的依赖性。应该用括号来保证运算顺序。
(3)不允许将sizeof运算符作用于有副作用的表达式上。如:j = sizeof(i = 1234)实际上在运算时被替换为:j = sizeof(int32_t),因为sizeof运算符只针对数据类型进行操作。
(4)逻辑运算(&&和||)的右操作数不允许包含副作用。
(5)逻辑运算符的操作数必须是一个主表达式。
(6)逻辑运算符(&&和||以及!)的操作数必须是一个有效的布尔值,布尔值表达式不允许进行逻辑运算以外的操作。
(7)不允许对又符号数进行位操作。
(8)移位操作的右操作数只能在0和操作数的位数减1之间。
(9)不允许无符号性的表达式使用一元负运算符。
(10)不允许使用逗号表达式。
(11)不允许对浮点型值进行位操作。
(12)不允许在同一个表达式中混合使用++和--。
6、程序流的控制规范
(1)禁止在产生布尔值的表达式中使用赋值运算符。
(2)判断一个值是否为0应该是显示的,除非操作数是一个布尔值。
(3)禁止对浮点数类型的变量或表达式做比较操作。
(4)for循环的控制表达式不应该包含浮点数类型。
(5)for循环语句的三个表达式应该仅与循环控制相关。
(6)禁止在循环中修改循环计数器。
(7)布尔表达式的值必须是可改变的。
(8)非空的switch子句都应该以break语句结束。
(9)switch语句的主体必须是复合语句(即用大括号包含)
(10)switch的最后一个子句必须是default子句,如果default中没有包含任何语句,那么应该使用注释来说明为什么没有进行任何操作。
(11)switch的 表达式中不能出现有效的布尔值类型。
(12)每一个switch语句必须至少包含一个case子句。
(13)不能存在无法执行的代码。
(14)非空语句要么必须产生副作用(side-effect)(副作用是指表达式执行后对程序运行环境造成的影响。赋值语句、自增操作等都是典型的具有副作用的操作),要么使程序流程改变。
(15)一行中如果有空语句,那么改行只能有这条空语句,不能有别的语句,并且在这条空语句前不能有注释,注释必须在其后,用空格隔开。
(16)不允许使用goto语句。
(17)不允许使用continue语句。
(18)循环体中最多只能出现一个break语句用于结束循环。
(19)函数只能有一个出口,这个出口必须在函数末尾。
(20)switch、while、do...while和for语句的主体必须是复合语句(即大括号包含),即使该主体只包含一条语句。
(21)if结构后面必须是一个复合语句,else后面必须是一个复合语句或者另一个if语句。
(22)if.....else if 结构必须由一个else子句结束。
7、函数相关规范
1)函数的定义和声明
(1)函数的每一个参数类型在声明与定义中必须一致,函数的返回类型也应一致。
(2)头文件中不允许包含对象或函数的定义。
(3)函数必须声明原型,在函数定义和调用时原型必须可见。
(4)不允许定义参数数量不确定的函数。
(5)在函数的原型声明中应该为所有参数给出标识符。
(6)函数原型中的参数与实际定义中的形参必须一致。
(7)不带参数的函数应该声明为具有void类型的参数。
2)函数的调用和使用
(1)函数不得调用本身,无论是直接调用还是间接调用。(一般禁止使用递归或预估递归层数)
(2)传递给函数的参数个数必须与函数定义的参数一致。
(3)非void函数中每一个return语句必须有返回值。

猜你喜欢

转载自blog.csdn.net/hushaoqiqimingxing/article/details/81047527