Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有非连续布局的C位字段元素_C_Struct_Embedded_Unions_Bit Fields - Fatal编程技术网

具有非连续布局的C位字段元素

具有非连续布局的C位字段元素,c,struct,embedded,unions,bit-fields,C,Struct,Embedded,Unions,Bit Fields,我正在寻找最优雅的接口上的输入,以放置在内存映射寄存器接口周围,其中目标对象在寄存器中拆分: union __attribute__ ((__packed__)) epsr_t { uint32_t storage; struct { unsigned reserved0 : 10; unsigned ICI_IT_2to7 : 6; // TOP HALF unsigned reserved1 : 8;

我正在寻找最优雅的接口上的输入,以放置在内存映射寄存器接口周围,其中目标对象在寄存器中拆分:

union __attribute__ ((__packed__)) epsr_t {
    uint32_t storage;
    struct {
        unsigned reserved0    : 10;
        unsigned ICI_IT_2to7  :  6; // TOP HALF
        unsigned reserved1    :  8;
        unsigned T            :  1;
        unsigned ICI_IT_0to1  :  2; // BOTTOM HALF
        unsigned reserved2    :  5;
    } bits;
};
在这种情况下,访问单个位
T
或任何
保留
字段都可以正常工作,但要读取或写入
ICI\u IT
需要类似以下代码:

union epsr_t epsr;
// Reading:
uint8_t ici_it = (epsr.bits.ICI_IT_2to7 << 2) | epsr.bits.ICI_IT_0to1;
// Writing:
epsr.bits.ICI_IT_2to7 = ici_it >> 2;
epsr.bits.ICI_IT_0to1 = ici_it & 0x3;
union epsr\u t epsr;
//阅读:
uint8_t ici_it=(epsr.bits.ici_it 2to7>2;
epsr.bits.ICI_IT_0to1=ICI_IT&0x3;
此时,我已经失去了位域抽象试图提供的简单性/便利性。我考虑了宏解决方案:

#define GET_ICI_IT(_e)      ((_e.bits.ICI_IT_2to7 << 2) | _e.bits.ICI_IT_0to1)
#define SET_ICI_IT(_e, _i)  do {\
    _e.bits.ICI_IT_2to7 = _i >> 2;\
    _e.bits.ICI_IT_0to1 = _i & 0x3;\
    while (0);
#定义GET_ICI_IT(_e.bits.ICI_IT_2to7>2\
_e、 bits.ICI_IT_0to1=_i&0x3\
而(0);

但一般来说,我不太喜欢这样的宏,我讨厌在阅读别人的代码时追查它们,我决不会给别人造成这样的痛苦。我希望有一个创造性的技巧,包括结构/联合/你有什么可以更优雅地隐藏这个对象的分裂性质(理想情况下作为对象的简单成员).

如果你那么不喜欢宏,只需使用内联函数,但你的宏解决方案很好。

我认为没有“好”的方法,事实上我不会依赖于位域……有时候最好是有一堆详尽的宏来完成你想做的一切,好好记录它们,然后完全依赖它们你的问题

#define ICI_IT_HI_SHIFT   14
#define ICI_IT_HI_MASK    0xfc
#define ICI_IT_LO_SHIFT   5
#define ICI_IT_LO_MASK    0x02

// Bits containing the ICI_IT value split in the 32-bit EPSR
#define ICI_IT_PACKED_MASK  ((ICI_IT_HI_MASK << ICI_IT_HI_SHIFT) |     \
                             (ICI_IT_LO_MASK << ICI_IT_LO_SHIFT))

// Packs a single 8-bit ICI_IT value x into a 32-bit EPSR e
#define PACK_ICI_IT(e,x)  ((e & ~ICI_IT_PACKED_MASK) |                 \
                           ((x & ICI_IT_HI_MASK) << ICI_IT_HI_SHIFT) | \
                           ((x & ICI_IT_LO_MASK) << ICI_IT_LO_SHIFT)))

// Unpacks a split 8-bit ICI_IT value from a 32-bit EPSR e
#define UNPACK_ICI_IT(e)  (((e >> ICI_IT_HI_SHIFT) & ICI_IT_HI_MASK) | \
                           ((e >> ICI_IT_LO_SHIFT) & ICI_IT_LO_MASK)))
#定义ICI_IT_HI_SHIFT 14
#定义ICI_IT_HI_掩码0xfc
#定义ICI\u IT\u LO\u班次5
#定义ICI\u IT\u LO\u掩码0x02
//包含在32位EPSR中拆分的ICI_IT值的位
#定义ICI_IT_压缩_掩码((ICI_IT_HI_掩码ICI_IT_LO_SHIFT)和ICI_IT_LO_掩码)))

请注意,为了可读性,我没有加入类型转换和普通宏内容。是的,我在提到可读性时得到了讽刺…

您的编译器支持匿名联合吗

我发现它是一个优雅的解决方案,它摆脱了你的
.bits
部分。它不符合C99,但大多数编译器都支持它。它成为了C11的标准


另请参见以下问题:.

坚持使用宏,真的。如果你想让你的代码更有趣,假设你有读/写epsr函数,让它们接受struct两个字段(T和ICC_IT),并在函数中将其从/转换为espr_T。位字段非常不可靠,esp就是这样使用的(指向另一个编译域或硬件中的某物)。硬件不是动态的,不会改变(不需要定义一次并使用多次)。不管怎样,位字段将导致掩码和移位,只需直接或在宏中对掩码和移位进行编码。当它们实际出现问题时,您是否有任何指针或引用?这是嵌入式空间中一个非常常见的习惯用法,当然不是我发明的。。Dan Saks在www.embedded.com上详细介绍了这个问题这些年。这是他的一篇文章的一部分,但还有其他几篇可能会对您有所帮助。只需一句话。您不需要命名结构中未使用的字段。删除reserved0、reserved1和reserved2名称效果绝对不错。这对于不需要设置这些字段的初始值设定器来说有好处。好奇您为什么要这样做避免位字段?对于32位体系结构(当前上下文)上的单个字大小的结构,情况定义得非常好据我所知,位域不受C标准的限制。编译器可以或多或少地以它选择的任何方式实现它们。如果你在单个平台上使用单个编译器,也许可以。但我不喜欢依赖它们。据我所知,它至少有义务保持域的有序。在这一点上,early断言(sizeof(union epsr_t)==4)这足以让偏执狂验证事情是否如预期的那样。在这一点上,我发现可读性大大提高。另外,当避免使用宏时,调试器和其他工具可以获得很好的功能。这很好。我不是专家,也许我的方式也有点老套。但是当我为一个定义非常好的协议安排大量位时,我只是不太信任位域,就像我信任冷硬位操作一样。使用宏来完成所有操作会使代码更难维护,但一旦我出于某种目的开发了一组宏,我会非常仔细地测试它们,然后再也不碰它们。这是合理的,它只是不可伸缩。从100个寄存器开始,其中大部分是ch有5~20个组件,你真的开始欣赏比特域方法的可扩展性和可读性。不管怎样,我认为我已经解决了这个问题,只是想把它扔到世界各地。你的解决方案会是什么样子,去掉了.bit?回顾我的答案(这么多年之后),它没有多大意义:它没有提供一个解决方案。仍然需要变戏法。