2

假设我有

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,这会变成 M​​ISRA 错误: 表达式分配给更窄或不同的基本类型。

我试图限制使用的位数,但没有成功。

foo.bf.bar = (myValue 0x1U)

如果我必须使用 uint16_t 值作为原点,是否有机会使其符合 MISRA 标准?

4

2 回答 2

3

MISRA-C 的基本类型模型并不真正适用于位域。术语更窄和更宽是指以字节为单位的大小(见 8.10.2)。因此,静态分析器是否应该在此处发出警告并不明显,因为基本类型的规则不涉及位域。
编辑:我在这里错了,请参阅 Andrew 的回答。附录 D.4 讲述了如何将位域类型转换为匹配的基本类型类别。

然而,在 MISRA-C 应用程序中使用位域是个坏主意。标准对位域的规定非常差,因此是不确定的和不可靠的。此外,MISRA-C 6.1 要求您记录编译器如何支持位域uint16_t,因为这不是位域允许的标准整数类型之一。

但这里真正的交易破坏者是指令 1.1,它要求记录和理解所有实现定义的行为。对于 MISRA-C 实现,我曾经尝试过记录位域的所有实现定义方面。很快我发现自己写了一篇完整的文章,因为它们有很多问题。看到这个冰山的顶部。

不必编写这样的“位域行为手册”的解决方法是在您的编码标准中完全无条件地禁止使用位域。无论如何,它们都是 100% 多余的功能。请改用按位运算符。

于 2018-09-21T07:07:22.177 回答
1

MISRA C:2012 的附录 D.4 有用地命名为“位域的基本类型”

  • 对于用本质上是 Boolean 类型实现的位域,它本质上是 Boolean
  • 对于使用有符号类型实现的位域,它是能够表示位域的最低等级的有符号类型
  • 对于使用无符号类型实现的位域,它是能够表示位域的最低等级的无符号类型

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

除了观察到这看起来像是 PC-Lint 的误诊之外,一种避免任何怀疑可能性的解决方法将强制转换:

foo.bf.bar = (uint8_t)myValue

顺便说一句,MISRA C:2012 规则 6.1 提供了关于位域使用除有符号/无符号 int 以外的类型的指导......

于 2018-09-24T09:52:11.067 回答