# Misra C++ 2008 规范


# Misra Cpp 2008 规范

----

## 语言无关问题

### 不必要的构造

规则 0-1-1 （必需）项目不应包含无法访问的代码。

规则 0-1-2 （必需）项目不应包含不可行的路径。

规则 0-1-3 （必需）项目不应包含未使用的变量。

规则 0-1-4 （必需）项目不应包含只有一种用途的非易失性 POD 变量。

规则 0-1-5 （必需）项目不应包含未使用的类型声明。

规则 0-1-6 （必需）项目不应包含非易失性变量的实例，这些变量被赋予了以后从未使用过的值。

规则 0-1-7 （必需）应始终使用具有非 void 返回类型且不是重载运算符的函数返回的值。

规则 0-1-8 （必需）所有返回类型为 void 的函数都应具有外部副作用。

规则 0-1-9 （必需）不得有死代码。

规则 0-1-10（必需）每个定义的函数应至少调用一次。

规则 0-1-11（必需）在非虚拟函数中不得有未使用的参数（命名或未命名）。

规则 0-1-12（必需）在虚拟函数和覆盖它的所有函数的参数集中不应有未使用的参数（命名或未命名）。

### 贮存

规则 0-2-1（必需）不应将对象分配给重叠对象。

### 运行时失败

规则 0-3-1（文档）应通过使用以下至少一项来确保运行时故障的最小化：

1. 静态分析工具/技术；

2. 动态分析工具/技术；

3. 显式编码检查以处理运行时错误。

规则 0-3-2（必需）如果函数生成错误信息，则应测试该错误信息。

### 算术

规则 0-4-1（文档）应记录缩放整数或定点算术的使用。

规则 0-4-2（文档）应记录浮点运算的使用。

规则 0-4-3（文档）浮点实现应符合定义的浮点标准。

----

## 一般的

### 语言

规则 1-0-1（必需）所有代码均应符合 ISO/IEC 14882:2003“包含技术勘误 1 的 C++ 标准”。

规则 1-0-2（必需）仅当多个编译器具有通用的、已定义的接口时，才能使用它们。

规则 1-0-3（文档）应确定并记录所选编译器中整数除法的实现。

----

## 词汇约定

### 字符集

规则 2-2-1（文档）字符集和相应的编码应记录在案。

### 三字序列

规则 2-3-1（必需）不得使用三合符。

### 替代令牌

规则 2-5-1（建议）不应使用有向图。

### 注释

规则 2-7-1（必需）字符序列 /* 不得在 C 样式注释中使用。

规则 2-7-2（必需）不得使用 C 样式注释“注释掉”代码部分。

规则 2-7-3（建议）不应使用 C++ 注释“注释掉”代码部分。

＃＃＃＃ 身份标识

规则 2-10-1（必需）不同的标识符应在印刷上明确。

规则 2-10-2（必需）在内部范围内声明的标识符不应隐藏在外部范围内声明的标识符。

规则 2-10-3（必需）typedef 名称（包括限定，如果有的话）应是唯一标识符。

规则 2-10-4（必需）类、联合或枚举名称（包括限定，如果有）应是唯一标识符。

规则 2-10-5（必需）不应重复使用具有静态存储持续时间的非成员对象或函数的标识符名称。

规则 2-10-6（必需）如果一个标识符指代一个类型，它不应该指代同一范围内的一个对象或一个函数。

### 字面量

规则 2-13-1（必需）仅应使用 ISO/IEC 14882:2003 中定义的转义序列。

规则 2-13-2（必需）不得使用八进制常量（非零）和八进制转义序列（非“\0”）。

规则 2-13-3（必需）应将“U”后缀应用于所有无符号类型的八进制或十六进制整数文字。

规则 2-13-4（必需）文字后缀应为大写。

规则 2-13-5（必需）不应连接窄和宽字符串文字。

----

## 基本概念

### 声明和定义

规则 3-1-1（必需）应该可以在多个翻译单元中包含任何头文件而不违反单一定义规则。

规则 3-1-2（必需）不应在块范围内声明函数。

规则 3-1-3（必需）当声明一个数组时，它的大小应显式声明或通过初始化隐式定义。

### 一个定义规则

规则 3-2-1（必需）对象或函数的所有声明都应具有兼容的类型。

规则 3-2-2（必需）不得违反单一定义规则。

规则 3-2-3（必需）在多个翻译单元中使用的类型、对象或函数应在一个且仅一个文件中声明。

规则 3-2-4（必需）具有外部链接的标识符应具有准确的定义。

### 声明性区域和范围

规则 3-3-1（必需） 具有外部链接的对象或函数应在头文件中声明。

规则 3-3-2（必需）如果函数具有内部链接，则所有重新声明都应包括静态存储类说明符。

### 名称查询

规则 3-4-1（必需）声明为对象或类型的标识符应在块中定义，以使其可见性最小化。

### 类型

规则 3-9-1（必需）在所有声明和重新声明中，用于对象、函数返回类型或函数参数的类型应逐个令牌相同。

规则 3-9-2（建议）指示大小和符号的 typedef 应该用来代替基本的数字类型。

规则 3-9-3（必需）不应使用浮点值的底层位表示。

----

## 标准转换

### 整体促销

规则 4-5-1（必需）除了赋值运算符 =、逻辑运算符 &&、||、!、等式运算符 == 和 != 之外，不应将 bool 类型的表达式用作内置运算符的操作数，一元 & 运算符和条件运算符。

规则 4-5-2（必需）类型为 enum 的表达式不得用作除下标运算符 [ ]、赋值运算符 =、相等运算符 == 和 !=、一元 & 运算符之外的内置运算符的操作数，以及关系运算符 <、<=、>、>=。

规则 4-5-3（必需）类型（纯）char 和 wchar_t 的表达式不得用作除赋值运算符 =、相等运算符 == 和 != 以及一元 & 运算符之外的内置运算符的操作数.

### 指针转换

规则 4-10-1（必需）不得将 NULL 用作整数值。

规则 4-10-2（必需）不应将文字零 (0) 用作空指针常量。

----

## 表达式

### 主要表达式

规则 5-0-1 （必需）在标准允许的任何评估顺序下，表达式的值都应相同。

规则 5-0-2 （建议）有限的依赖应该放在表达式中的 C++ 运算符优先规则上。

规则 5-0-3 （必需）不得将 cvalue 表达式隐式转换为不同的基础类型。

规则 5-0-4 （必需）隐式整数转换不应改变底层类型的符号。

规则 5-0-5 （必需）不应有隐式浮点整数转换。

规则 5-0-6 （必需）隐式整数或浮点转换不应减少基础类型的大小。

规则 5-0-7 （必需）不应有 cvalue 表达式的显式浮点整数转换。

规则 5-0-8 （必需）显式整数或浮点转换不应增加 cvalue 表达式的基础类型的大小。

规则 5-0-9 （必需）显式整数转换不应更改 cvalue 表达式的基础类型的符号。

规则 5-0-10（必需）如果按位运算符 ~ 和 << 应用于基础类型为 unsigned char 或 unsigned short 的操作数，则结果应立即转换为操作数的基础类型。

规则 5-0-11（必需）plain char 类型只能用于存储和使用字符值。

规则 5-0-12（必需）有符号字符和无符号字符类型只能用于数值的存储和使用。

规则 5-0-13（必需）if 语句的条件和迭代语句的条件应具有 bool 类型。

规则 5-0-14（必需）条件运算符的第一个操作数应具有 bool 类型。

规则 5-0-15（必需）数组索引应是指针运算的唯一形式。

规则 5-0-16（必需）指针操作数和使用该操作数的指针运算产生的任何指针都应寻址同一数组的元素。

规则 5-0-17（必需）指针之间的减法仅适用于寻址同一数组元素的指针。

规则 5-0-18（必需）>、>=、<、<= 不应应用于指针类型的对象，除非它们指向同一个数组。

规则 5-0-19（必需）对象的声明应包含不超过两级指针间接。

规则 5-0-20（必需）二进制位运算符的非常量操作数应具有相同的基础类型。

规则 5-0-21（必需）位运算符只能应用于无符号基础类型的操作数。

### 后缀表达式

规则 5-2-1 （必需）逻辑 && 或 || 的每个操作数 应该是一个后缀表达式。

规则 5-2-2 （必需）只能通过 dynamic_cast 将指向虚拟基类的指针转换为指向派生类的指针。

规则 5-2-3 （建议）不应在多态类型上执行从基类到派生类的强制转换。

规则 5-2-4 （必需）不应使用 C 样式转换（除了 void 转换）和功能符号转换（除了显式构造函数调用）。

规则 5-2-5 （必需）强制转换不得从指针或引用的类型中删除任何 const 或 volatile 限定。

规则 5-2-6 （必需）强制转换不应将指向函数的指针转换为任何其他指针类型，包括指向函数类型的指针。

规则 5-2-7 （必需）不得将具有指针类型的对象直接或间接转换为不相关的指针类型。

规则 5-2-8 （必需）不得将整数类型的对象或指向 void 类型的指针转​​换为指针类型的对象。

规则 5-2-9 （建议）强制转换不应将指针类型转换为整数类型。

规则 5-2-10（建议）增量 (++) 和减量 (--) 运算符不应与表达式中的其他运算符混合。

规则 5-2-11（必需）逗号运算符、&& 运算符和 || 运算符不应超载。

规则 5-2-12（必需）作为函数参数传递的数组类型的标识符不应衰减为指针。

### 一元表达式

规则 5-3-1（必需） ! 的每个操作数 运算符，逻辑 && 或逻辑 || 运算符的类型应为 bool。

规则 5-3-2（必需）一元减号运算符不应应用于基础类型为无符号的表达式。

规则 5-3-3（必需）一元 & 运算符不应被重载。

规则 5-3-4（必需）对 sizeof 运算符的操作数的评估不应包含副作用。

### 移位运算符

规则 5-8-1（必需）移位运算符的右手操作数应位于比左手操作数的基础类型的位宽度小 0 到 1 之间。

### 逻辑与运算符

规则 5-14-1（必需）逻辑 && 或 || 的右手操作数 运算符不得包含副作用。

### 赋值运算符

规则 5-17-1（必需）应保留二元运算符及其赋值运算符形式之间的语义等价性。

### 逗号运算符

规则 5-18-1（必需）不得使用逗号运算符。

### 常量表达式

规则 5-19-1（建议）对常量无符号整数表达式的求值不应导致回绕。

----

## 语句

### 表达式语句

规则 6-2-1（必需）赋值运算符不得用于子表达式。

规则 6-2-2（必需）不应直接或间接测试浮点表达式是否相等或不相等。

规则 6-2-3（必需）在预处理之前，空语句只能出现在一行上；如果空语句后面的第一个字符是空白字符，则它后面可以跟注释。

### 复合语句

规则 6-3-1（必需）构成 switch、while、do ... while 或 for 语句主体的语句应为复合语句。

### 选择语句

规则 6-4-1（必需）if (condition) 构造后应跟复合语句。else 关键字后应跟复合语句或另一个 if 语句。

规则 6-4-2（必需）所有 if - else if 结构应以 else 子句终止。

规则 6-4-3（必需）switch 语句应是格式良好的 switch 语句。

规则 6-4-4（必需）仅当最封闭的复合语句是 switch 语句的主体时，才应使用 switch-label。

规则 6-4-5（必需）无条件的 throw 或 break 语句应终止每个非空 switch 子句。

规则 6-4-6（必需）switch 语句的最后一个子句应为默认子句。

规则 6-4-7（必需）switch 语句的条件不得为 bool 类型。

规则 6-4-8（必需）每个 switch 语句应至少有一个 case 子句。

----

## 迭代语句

### for 语句

规则 6-5-1（必需）for 循环应包含一个不具有浮点类型的循环计数器。

规则 6-5-2（必需）如果循环计数器未被 -- 或 ++ 修改，则在条件内，循环计数器应仅用作 <=、<、> 或 >= 的操作数。

规则 6-5-3（必需）不得在条件或语句中修改循环计数器。

规则 6-5-4（必需）循环计数器应修改为以下之一：--、++、-=n 或 +=n；其中 n 在循环期间保持不变。

规则 6-5-5（必需）不得在条件或表达式内修改循环计数器以外的循环控制变量。

规则 6-5-6（必需）除了在语句中修改的循环计数器之外的循环控制变量应具有 bool 类型。

### 跳转语句

规则 6-6-1（必需）goto 语句引用的任何标签都应在同一块中声明，或在包含 goto 语句的块中声明。

规则 6-6-2（必需）goto 语句应跳转到稍后在同一函数体中声明的标签。

规则 6-6-3（必需）continue 语句只能在格式良好的 for 循环中使用。

规则 6-6-4（必需）对于任何迭代语句，用于循环终止的 break 或 goto 语句不得超过一个。

规则 6-6-5（必需）函数应在函数末尾有一个退出点。

----

## 声明

### 说明符

规则 7-1-1（必需）未修改的变量应为 const 限定的。

规则 7-1-2（必需）如果相应对象未修改，函数中的指针或引用参数应声明为指向 const 的指针或对 const 的引用。

规则 7-1-3（必需）具有枚举基础类型的表达式应仅具有与枚举的枚举数相对应的值。

### 枚举声明

规则 7-2-1（必需）具有枚举基础类型的表达式应仅具有与枚举的枚举数相对应的值。

### 命名空间

规则 7-3-1（必需）全局命名空间应仅包含 main、命名空间声明和 extern "C" 声明。

规则 7-3-2（必需）标识符 main 不得用于除全局函数 main 之外的函数。

规则 7-3-3（必需）头文件中不应有未命名的名称空间。

规则 7-3-4（必需）不得使用使用指令。

规则 7-3-5（必需）同一命名空间中标识符的多个声明不应跨越该标识符的 using 声明。

规则 7-3-6（必需）不应在头文件中使用 Using-directives 和 using-declarations（不包括类范围或函数范围 using-declarations）。

### asm 声明

规则 7-4-1（文档） 汇编程序的所有使用都应记录在案。

规则 7-4-2（必需）只能使用 asm 声明引入汇编程序指令。

规则 7-4-3（必需）汇编语言应被封装和隔离。

### 联动规格

规则 7-5-1（必需）函数不应返回指向函数内定义的自动变量（包括参数）的引用或指针。

规则 7-5-2（必需）不应将具有自动存储功能的对象的地址分配给在第一个对象不再存在后可能持续存在的另一个对象。

规则 7-5-3（必需）函数不应返回引用或指向通过引用或 const 引用传递的参数的指针。

规则 7-5-4（建议）函数不应直接或间接调用自身。

----

## 声明符

＃＃＃＃ 一般的

规则 8-0-1（必需）一个 init-declarator-list 或一个 member-declarator-list 应分别由一个单独的 init-declarator 或 member-declarator 组成。

### 声明符的含义

规则 8-3-1（必需）覆盖虚函数中的参数应使用与它们覆盖的函数相同的默认参数，否则不应指定任何默认参数。

### 函数定义

规则 8-4-1（必需）不应使用省略号来定义函数。

规则 8-4-2（必需）函数重新声明中用于参数的标识符应与声明中的标识符相同。

规则 8-4-3（必需）具有非 void 返回类型的函数的所有退出路径都应具有带有表达式的显式返回语句。

规则 8-4-4（必需）函数标识符应用于调用函数，或者应以 & 开头。

### 初始化器

规则 8-5-1（必需）所有变量在使用前都应具有定义的值。

规则 8-5-2（必需）在数组和结构的非零初始化中，应使用大括号来指示和匹配结构。

规则 8-5-3（必需）在枚举器列表中，= 构造不应用于显式初始化除第一个之外的成员，除非所有项目都显式初始化。

----

## 类

### 成员函数

规则 9-3-1（必需）Const 成员函数不应返回非常量指针或对类数据的引用。

规则 9-3-2（必需）成员函数不应将非常量句柄返回给类数据。

规则 9-3-3（必需）如果成员函数可以设为静态，则应设为静态，否则如果可设为 const，则应设为 const。

### 工会

规则 9-5-1（必需）不得使用工会。

### 位域

规则 9-6-1（必需）当需要对表示位域的位进行绝对定位时，应记录位域的行为和打包。

规则 9-6-2（必需）位域应为 bool 类型或显式无符号或有符号整数类型。

规则 9-6-3（必需）位域不应具有枚举类型。

规则 9-6-4（必需）带符号整数类型的命名位字段的长度应超过一位。

----

## 派生类

### 多个基类

规则 10-1-1（建议） 类不应从虚拟库派生。

规则 10-1-2（必需）只有在菱形层次结构中使用基类时才应将其声明为虚拟的。

规则 10-1-3（必需）可访问的基类在同一层次结构中不应既是虚拟的又是非虚拟的。

### 成员名称查找

规则 10-2-1（建议）多重继承层次结构中的所有可访问实体名称都应该是唯一的。

### 虚函数

规则 10-3-1（必需）通过继承层次结构的每条路径上的每个虚函数的定义不得超过一个。

规则 10-3-2（必需）每个覆盖的虚函数都应使用 virtual 关键字声明。

规则 10-3-3（必需）只有当虚函数本身被声明为纯虚函数时，它才能被纯虚函数覆盖。

----

##会员访问控制

＃＃＃＃ 一般的

规则 11-0-1（必需）非 POD 类类型中的成员数据应是私有的。

----

## 特殊成员函数

### 构造函数

规则 12-1-1（必需）不应从其构造函数或析构函数的主体中使用对象的动态类型。

规则 12-1-2（建议）一个类的所有构造函数都应该显式调用它的所有直接基类和所有虚拟基类的构造函数。

规则 12-1-3（必需）所有可使用基本类型的单个参数调用的构造函数都应显式声明。

### 复制类对象

规则 12-8-1（必需）复制构造函数只能初始化它的基类和它所属的类的非静态成员。

规则 12-8-2（必需）复制赋值运算符应在抽象类中声明为受保护或私有。

----

## 模板

### 模板声明

规则 14-5-1（必需）只能在非关联命名空间的命名空间中声明非成员泛型函数。

规则 14-5-2（必需）当存在具有单个参数的模板构造函数是泛型参数时，应声明复制构造函数。

规则 14-5-3（必需）当模板赋值运算符的参数是泛型参数时，应声明复制赋值运算符。

### 名称解析

规则 14-6-1（必需）在具有依赖基的类模板中，可以在该依赖基中找到的任何名称都应使用限定 ID 或 this->

规则 14-6-2（必需）重载决议选择的函数应解析为先前在翻译单元中声明的函数。

### 模板实例化和特化

规则 14-7-1（必需）所有类模板、函数模板、类模板成员函数和类模板静态成员应至少实例化一次。

规则 14-7-2（必需）对于任何给定的模板特化，使用特化中使用的模板参数的模板的显式实例化不应导致程序格式错误。

规则 14-7-3（必需）模板的所有部分和显式特化应在与其主模板的声明相同的文件中声明。

### 函数模板特化

规则 14-8-1（必需）重载的函数模板不应明确专门化。

规则 14-8-2（建议）函数调用的可行函数集应该不包含函数特化，或者只包含函数特化。

----

## 异常处理

### 一般的

规则 15-0-1（文档）异常只能用于错误处理。

规则 15-0-2（建议）异常对象不应具有指针类型。

规则 15-0-3（必需）不得使用 goto 或 switch 语句将控制转移到 try 或 catch 块中。

### 抛出异常

规则 15-1-1（必需）throw 语句的赋值表达式本身不应导致抛出异常。

规则 15-1-2（必需）不应显式抛出 NULL。

规则 15-1-3（必需）空的 throw (throw;) 只能用在 catch 处理程序的复合语句中。

### 处理异常

规则 15-3-1（必需）仅在程序启动后和程序终止前才应提出异常。

规则 15-3-2（建议）应该至少有一个异常处理程序来捕获所有未处理的异常

规则 15-3-3（必需）类构造函数或析构函数的函数尝试块实现的处理程序不得引用此类或其基类的非静态成员。

规则 15-3-4（必需）在代码中显式抛出的每个异常都应在可能导致该点的所有调用路径中具有兼容类型的处理程序。

规则 15-3-5（必需）类类型异常应始终通过引用来捕获。

规则 15-3-6（必需）如果在单个 try-catch 语句或函数try-block 中为派生类及其部分或全部基类提供多个处理程序，则处理程序应按最派生到基类的顺序排列.

规则 15-3-7（必需）如果在单个 try-catch 语句或函数尝试块中提供多个处理程序，则任何省略号（catch-all）处理程序应最后出现。

### 异常规范

规则 15-4-1（必需）如果使用异常规范声明函数，那么（在其他翻译单元中）同一函数的所有声明都应使用相同的类型 ID 集进行声明。

### 特殊功能

规则 15-5-1（必需）类析构函数不应异常退出。

规则 15-5-2（必需）如果函数声明包含异常规范，则函数只能抛出指定类型的异常。

规则 15-5-3（必需）不应隐式调用 terminate() 函数。

----

## 预处理指令

＃＃＃＃ 一般的

规则 16-0-1（必需）文件中的 #include 指令只能位于其他预处理器指令或注释之前。

规则 16-0-2（必需）宏在全局命名空间中只能是 #define-d 或 #undef-d。

规则 16-0-3（必需）不得使用#undef。

规则 16-0-4（必需）不应定义类似函数的宏。

规则 16-0-5（必需）类函数宏的参数不应包含看起来像预处理指令的标记。

规则 16-0-6（必需）在类函数宏的定义中，参数的每个实例都应括在括号中，除非它用作 # 或 ## 的操作数。

规则 16-0-7（必需）在 #if 或 #elif 预处理器指令中不得使用未定义的宏标识符，除非作为已定义运算符的操作数。

规则 16-0-8（必需）如果 # 标记作为一行中的第一个标记出现，那么它应该紧跟一个预处理标记。

### 条件包含

规则 16-1-1（必需）定义的预处理器操作符只能以两种标准形式之一使用。

规则 16-1-2（必需）所有 #else、#elif 和 #endif 预处理器指令应与它们相关的 #if 或 #ifdef 指令位于同一文件中。

### 源文件包含

规则 16-2-1（必需）预处理器只能用于文件包含和包含保护。

规则 16-2-2（必需）C++ 宏只能用于包含防护、类型限定符或存储类说明符。

规则 16-2-3（必需）应提供包括防护装置。

规则 16-2-4（必需）'、"、/* 或 // 字符不得出现在头文件名中。

规则 16-2-5（建议） \ 字符不应出现在头文件名中。

规则 16-2-6（必需）#include 指令后应跟随 <filename> 或 “filename” 序列。

### 宏替换

规则 16-3-1（必需）在单个宏定义中最多应出现一次 # 或 ## 运算符。

规则 16-3-2（建议）不应使用 # 和 ## 运算符。

### Pragma 指令

规则 16-6-1（文档）#pragma 指令的所有使用都应记录在案。

----

## 库介绍

### 一般的

规则 17-0-1（必需）不得定义、重新定义或取消定义标准库中的保留标识符、宏和函数。

规则 17-0-2（必需）不得重用标准库宏和对象的名称。

规则 17-0-3（必需）标准库函数的名称不应被覆盖。

规则 17-0-4（文档）所有库代码应符合 MISRA C++。

规则 17-0-5（文档）不应使用 `setjmp` 宏和 `longjmp` 函数。

----

## 语言支持库

### 一般的

规则 18-0-1（必需）不得使用 `C` 库。

规则 18-0-2（必需）不应使用库 `<cstdlib>` 中的库函数 atof、atoi 和 atol。

规则 18-0-3（必需）不得使用库 `<cstdlib>` 中的库函数 abort、exit、getenv 和 system。

规则 18-0-4（必需）不得使用库 `<ctime>` 的时间处理功能。

规则 18-0-5（必需）不应使用库 `<cstring>` 的无界函数。

### 实现属性

规则 18-2-1（必需）不应使用宏 `offsetof`。

### 动态内存管理

规则 18-4-1（必需）不得使用动态堆内存分配。

### 其他运行时支持

规则 18-7-1（必需）不应使用 `<csignal>` 的信号处理设施。

----

## 诊断库

### 错误编号

规则 19-3-1（必需）不应使用错误指示符 `errno`。

----

## 输入/输出库

### 一般的

规则 27-0-1（必需）不应使用流输入/输出库 `<cstdio>`。

----


