假设我有
typedef struct {
unsigned short bar : 1;
} foo_bf;
typedef union {
unsigned short val;
foo_bf bf;
} foo_t;
如何从类型(例如uint16_t)正确地为此位字段分配一个值?
uint16_t myValue = 1;
foo_t foo;
foo.bf.bar = myValue
运行PC-Lint,这变成MISRA错误: 将表达分配给较窄或不同的基本类型。
我试图限制使用的位数,但没有成功。
foo.bf.bar = (myValue 0x1U)
如果我必须使用uint16_t值作为原点,是否有机会使其符合MISRA?
答案 0 :(得分:3)
MISRA-C的基本类型模型实际上不适用于位域。术语“更窄”和“更宽”是指以字节为单位的大小(请参见8.10.2)。因此,静态分析器是否应在此处发出警告并不明显,因为基本类型的规则未解决位字段。
编辑:我在这里错了,请参阅安德鲁的答案。附录D.4讲述了如何将位字段类型转换为匹配的基本类型类别。
但是,在MISRA-C应用程序中使用位域是一个坏主意。该标准对位字段的指定非常差,因此不确定且不可靠。另外,MISRA-C 6.1要求您使用uint16_t
记录编译器如何支持位域,因为这不是允许用于位域的标准整数类型之一。
但是真正的破坏者是Directive 1.1,它要求记录并理解所有实现定义的行为。对于MISRA-C实现,我实际上曾经尝试记录位域的所有实现定义方面。很快我发现自己写了整篇文章,因为它们有很多问题。 See this代表冰山的顶端。
不必写这样的“位域行为手册”的变通办法是无条件禁止在您的编码标准中完全使用位域。无论如何,它们是100%多余的功能。改为使用按位运算符。
答案 1 :(得分:1)
MISRA C:2012的附录D.4的标题为“比特字段的基本类型”。
一位无符号整数的最低排名的无符号类型将为 uint8_t (又名 unsigned char )-假设该工具不会将一位解释为布尔值...
除了观察到这看起来像是PC-Lint的错误诊断之外,一种避免任何疑问可能性的变通方法将投放:
foo.bf.bar = (uint8_t)myValue
顺便提一句,MISRA C:2012规则6.1给出了将有符号/无符号int以外的类型用于位域的指南...