对位域声明合理的类型
6.9.1 ID_improperBitfieldType
为了提高可移植性和可维护性,应对位域声明合理的类型,如:
- 显式声明 signed 或 unsigned 的整数类型
- C++ 语言的 bool 或 C 语言的 _Bool 类型
- 各种实现中取值范围均一致的整数类型
C90 标准只允许 int、signed int 或 unsigned int 作为位域类型,在之后的 C 标准以及 C++14 之前的 C++ 标准中,用于位域的 char、short、int、long 或 long long 等整数类型是否有符号由实现定义。
为了避免意料之外的符号扩展、溢出等问题,建议统一使用无符号整型作为位域类型。
示例:
struct A {
char c: 2; // Non-compliant
};
char 是否有符号由实现定义,位域 c 的取值范围可能是 [-2, 1] 也可能是 [0, 3],故应明确声明位域的符号属性:
struct A {
unsigned char c: 2; // Compliant, or use uint8_t
};
又如:
struct B {
unsigned long a: 4; // Bad
unsigned long b: 32; // Bad
unsigned long c: 24; // Bad
};
例中结构体只涉及 60 个比特位,但由于 long 的取值范围是由实现定义的,结构体的内存布局在不同的平台上会有较大差异,可能会产生意料之外的填充数据,造成对接口或协议的解析错误。
应改为:
#include <stdint.h> // Or <cstdint> in C++
struct B {
uint64_t a: 4; // OK
uint64_t b: 32; // OK
uint64_t c: 24; // OK
};
配置
bitfieldMustBeUnsigned: 位域类型是否必须为无符号整型
bitfieldMustBeStdInt: 位域类型是否必须为 stdint.h 或 cstdint 中定义的类型
依据
ISO/IEC 9899:1990 6.5.2.1
ISO/IEC 9899:1999 J.3.9(1)-implementation
ISO/IEC 9899:2011 J.3.9(1)-implementation
ISO/IEC 14882:2003 9.6(3)-implementation
ISO/IEC 14882:2011 9.6(3)-implementation
参考
MISRA C 2004 6.4
MISRA C 2012 6.1
MISRA C++ 2008 9-6-2