如何访问映射内存中的位?

时间:2017-02-21 09:17:52

标签: c gcc bit-manipulation cross-compiling bit-fields

想象!我从一个处理一些房屋自动化的IO接口收到8个字节uint8_t data[8]。这八个字节需要解释为休闲:

Memory interpretion

如何访问正确的位? 我现在想到了两个解决方案:

解决方案1:使用一些位域定义结构:

struct data_s {
  uint8_t LightSwitch0:1;
  uint8_t LightSwitch1:1;
  uint8_t LightSwitch2:1;
  uint8_t LightSwitch3:1;
  uint8_t Brightness:4;
  uint8_t Dimmer0;
  uint8_t Dimmer1;
  uint8_t Dimmer2;
  uint8_t Dimmer3;
  uint8_t Dimmer4;
  uint8_t DoorSwitch:1;
  uint8_t Spare:7;
}

接下来,根据这个例子,我可以简单地进行转换并访问结构成员:

data_s *foo = data;
foo->LightSwtich1 = FALSE;
foo->Brightness = 7;
//...

解决方案2:使用位掩码:

data[0] |= 0x02;
data[0] = (data[0] & 0x0F) | (( 7 << 4 ) & 0xF0)
//...

我知道位域是编译器所依赖的并且不是那么可移植的。这就是为什么解决方案2通常是首选。然而,解决方案2看起来更复杂,更难以阅读。如果映射的内存超过8个字节,那么它将会工作得更多。

我真的需要做解决方案2吗?或者我可以使用#pragma reverse_bitfields on指令来提高解决方案1的可移植性?如果代码仅针对具有交叉编译器的一个目标构建,我可以使用解决方案1吗?

所以我的问题是:我应该如何访问正确的位?

1 个答案:

答案 0 :(得分:3)

位域依赖于编译器的程度有点夸张。当你以奇怪的方式使用它们时,它们大多会变得怪异。

在您的示例中,所有字段都是无符号的并且具有相同的存储类型,它们都不跨越存储边界,并且没有未使用的位。存在排序位的问题(正如您所见),但近年来,每个人都采用相同的排序方式。据我所知,当前的编译器不会生成任何与您正在获得的IO数据不兼容的内容。