【问题标题】:Safe assign of values to bitfield in C将值安全分配给C中的位域
【发布时间】:2018-09-21 06:19:30
【问题描述】:

假设我有

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?

【问题讨论】:

  • myValue 转换为_Bool?如果这不起作用,您可能不得不忍受警告。
  • if (myValue) myFoo.bar = 1; else myFoo.bar = 0; 假设为foo_bf myFoo,垃圾邮件foo_t
  • 根据错误所指的较窄类型,foo.bf.bar = (unsigned short) myValue; 可能就足够了

标签: c bit-fields misra pc-lint


【解决方案1】:

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

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

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

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

【讨论】:

  • 考虑到 here 只需要一个标志(好吧,也许这只是一个例子),没有任何位域逻辑的 unsigned char 就可以了。
  • “非确定性”似乎有点强。我希望特定平台的单个编译器版本的行为 - 这是您通常会记录的内容,是吗? - 保持一致(对于任何值得认证的编译器)。记录下来真的有那么糟糕吗?
  • @Leushenko 存储单元的对齐方式不仅仅是实现定义的,它是未指定的。这意味着同一个编译器可以不时地做不同的事情,并且不需要记录何时或如何。所以是的,从程序员的角度来看,位域具有不确定的行为,只要它们被用作分配顺序或内存映射无关紧要的布尔标志块之外的其他东西。从编译器(内部)的角度来看,它们是确定性的。
【解决方案2】:

MISRA C:2012 的附录 D.4 标题为“位域的基本类型”很有用

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

一位无符号整数的 Unsigned Type of Lowest Rank 将是 uint8_t(又名 unsigned char) - 假设工具不会将单个位解释为布尔值...

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

foo.bf.bar = (uint8_t)myValue

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

【讨论】:

  • 我不知道该附录中的这一部分,因此我自己的部分答案似乎在基本类型方面不正确(将修复)。但是,什么是“签名类型”? C 标准显然没有指定 int : n 是布尔、有符号还是无符号类型。静态分析器应该如何知道特定目标的实现定义的行为? MISRA-C 应该完全禁止位域:在关键系统中绝不应该允许它们。
  • 附带说明一下,您是否听说过任何可怜的人实际上记录了位域的所有实现定义方面?根据指令 1.1 的要求。如果 MISRA 坚持允许位域,也许他们还应该发布一本应用笔记/书,其中包含所有实现定义的位域行为,这样 MISRA-C 的每个实现者都不必编写这样的书。
  • 很高兴向团队提出建议......当然,最好让 WG14 在标准中修复它 - 但我们知道这永远不会发生 :(
  • 位域在嵌入式系统中尤其是一个显着的危险,因为现在每个工具链都会得到一个位域混乱的微控制器寄存器映射。事实上,如果 WG14 真的修复了标准,就不需要 MISRA-C :)
猜你喜欢
  • 2015-01-15
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 2020-04-25
  • 2022-06-30
  • 2018-05-17
  • 2012-06-02
  • 1970-01-01
相关资源
最近更新 更多