将值安全分配给C中的位域

时间:2018-09-21 06:19:31

标签: c bit-fields misra pc-lint

假设我有

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?

2 个答案:

答案 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的标题为“比特字段的基本类型”。

  • 对于使用基本布尔类型实现的位域,它是基本布尔
  • 对于用 signed type 实现的位域,它是最低等级的Signed类型,它可以表示位域
  • 对于用 unsigned type 实现的位域,它是最低等级的无符号类型,它可以表示位域

一位无符号整数的最低排名的无符号类型将为 uint8_t (又名 unsigned char )-假设该工具不会将一位解释为布尔值...

除了观察到这看起来像是PC-Lint的错误诊断之外,一种避免任何疑问可能性的变通方法将投放:

foo.bf.bar = (uint8_t)myValue

顺便提一句,MISRA C:2012规则6.1给出了将有符号/无符号int以外的类型用于位域的指南...