如何访问映射内存中的位?
How to access bits in mapped memory?
想象一下!我从处理一些家庭自动化的 IO 接口收到 8 个字节作为 uint8_t data[8]
。这八个字节需要解释为fallows:
如何访问正确的位?
我现在想到了两个解决方案:
解决方案 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 看起来要复杂得多并且更难阅读。此外,如果映射内存超过八个字节,工作量会很大。
我真的需要执行解决方案 2 吗?或者我可以使用 #pragma reverse_bitfields on
指令来提高解决方案 1 的可移植性?如果代码是用交叉编译器只为一个目标构建的,我可以使用解决方案 1 吗?
所以我的问题是:我应该如何访问正确的位?
位域 compiler-dependent 的程度被夸大了。当您以奇怪的方式使用它们时,它们通常会变得很奇怪。
在您的示例中,所有字段都是无符号的并且具有相同的存储类型,其中 none 跨越存储边界,并且没有未使用的位。存在排序位的问题(如您所见),但近年来每个人都采用相同的排序。据我所知,当前的编译器不会生成任何与您获取的 IO 数据不兼容的内容。
想象一下!我从处理一些家庭自动化的 IO 接口收到 8 个字节作为 uint8_t data[8]
。这八个字节需要解释为fallows:
如何访问正确的位? 我现在想到了两个解决方案:
解决方案 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 看起来要复杂得多并且更难阅读。此外,如果映射内存超过八个字节,工作量会很大。
我真的需要执行解决方案 2 吗?或者我可以使用 #pragma reverse_bitfields on
指令来提高解决方案 1 的可移植性?如果代码是用交叉编译器只为一个目标构建的,我可以使用解决方案 1 吗?
所以我的问题是:我应该如何访问正确的位?
位域 compiler-dependent 的程度被夸大了。当您以奇怪的方式使用它们时,它们通常会变得很奇怪。
在您的示例中,所有字段都是无符号的并且具有相同的存储类型,其中 none 跨越存储边界,并且没有未使用的位。存在排序位的问题(如您所见),但近年来每个人都采用相同的排序。据我所知,当前的编译器不会生成任何与您获取的 IO 数据不兼容的内容。