与Endianness无关的代码与Union中的Bit字段

时间:2011-11-18 17:52:39

标签: c endianness

我想知道编写endianess独立代码的最佳方法是什么,尤其是在使用数组“test_attr [0] / test_attr [1]”访问位字段时??

struct tagTest
{
    union
    {
        struct
        {
            uint16 A:3;  
            uint16 B:3;  
            uint16 C:3;  
            uint16 D:3;  
            uint16 E:3;  
            uint16 F:1;
            uint16 G:3;  
            uint16 H:3;  
            uint16 I:3;  
            uint16 J:3;  
            uint16 K:4;  
        } Attributes;

        uint16 test_attr[2];  
    } EndianIndependent;
};               

3 个答案:

答案 0 :(得分:2)

在某些来源中使用以下方式:

struct
{
#if BYTE_ORDER == LITTLE_ENDIAN
   uint16 A:4;  
   uint16 B:4;  
   uint16 C:4;  
   uint16 D:4;  
#endif
#if BYTE_ORDER == BIG_ENDIAN
   uint16 D:4;  
   uint16 C:4;  
   uint16 B:4;  
   uint16 A:4;  
#endif
} Attributes;

但它看起来真的很难看。也许它不那么便携。 可能最好使用位掩码和位移而不是位文件。

答案 1 :(得分:1)

位字段排序依赖于实现,甚至不需要与目标的基本字节同步。 通过数组访问位字段更依赖于处理器和编译器。

编写独立代码的唯一机会是将访问封装在一组函数中,并在每个编译器/处理器组合上验证是否返回了正确的结果。

我在将代码从Freescale S12X移植到MPC56xx架构时遇到了同样的问题,这些转换非常乏味但不可避免。 MPC甚至以反方向对一个字中的位进行编号。去图!

答案 2 :(得分:0)

这根本不是便携式的,但就我而言,这对我帮助很大:)

#ifdef __LITTLE_ENDIAN
#define BITFIELD2(a,b) a;b;
#elif defined(__BIG_ENDIAN)
#define BITFIELD2(a,b) b;a;
#else
#error cannot decide architecture
#endif

#define BITFIELD3(a,b,c) BITFIELD2(a,BITFIELD2(b,c))
#define BITFIELD4(a,b,c,d) BITFIELD2(a,BITFIELD3(b,c,d))
#define BITFIELD5(a,b,c,d,e) BITFIELD2(a,BITFIELD4(b,c,d,e))
#define BITFIELD6(a,b,c,d,e,f) BITFIELD2(a,BITFIELD5(b,c,d,e,f))

struct
    {
        BITFIELD6(
        uint16 A:3,
        uint16 B:3,  
        uint16 C:3,  
        uint16 D:3,  
        uint16 E:3,  
        uint16 F:1
        )
        BITFIELD5(
        uint16 G:3,
        uint16 H:3,  
        uint16 I:3,  
        uint16 J:3,  
        uint16 K:4
        )
    } Attributes;