Bitfield联合用于轻松访问位,意外行为

时间:2014-10-30 09:59:30

标签: c unions bit-fields

我建立了这个联合,以便在位和整数之间轻松地来回访问。 (事实上​​,我找了一种方法来r / w一个有符号int的所有位,很容易,没有可移植性的陷阱,我很好地搞砸了)

typedef union {
    struct {
         unsigned int b32   : 1;
         unsigned int b31   : 1;
         unsigned int b30   : 1;
         unsigned int b29   : 1;
         unsigned int b28   : 1;
         unsigned int b27   : 1;
         unsigned int b26   : 1;
         unsigned int b25   : 1;
         unsigned int b24   : 1;

         /* etc. */

         unsigned int b01   : 1; /* LSB */
    } field;
    uint32_t word;
    int32_t integer;
} Bit32Field_T;

正如预期的那样,每个bxx字段都允许我访问底层32字节整数的位。

但是,此代码仅对sparc(大端)CPU有效。对于little-endian(x86),我必须镜像每个字段,从b01到b32,以获得预期的行为。

typedef union {
    struct {
         unsigned int b01   : 1; /* LSB */
         unsigned int b02   : 1;
         unsigned int b03   : 1;
         unsigned int b04   : 1;
         unsigned int b05   : 1;
         unsigned int b06   : 1;
         unsigned int b07   : 1;
         unsigned int b08   : 1;
         unsigned int b09   : 1;

         /* etc. */

         unsigned int b32   : 1;
    } field;
    uint32_t word;
    int32_t integer;
} Bit32Field_T;

我认为小端是关于反转字节而不是位!我应该如何理解所包装的包装?

(一切都用gcc编译,在solaris下用于BE,debian用于LE)

2 个答案:

答案 0 :(得分:0)

我遇到类似问题的方法,即将32位字从小端转换为大端,是:

unsigned char buf[4];
uint32_t word;

fread(buf, sizeof(buf), 1, fp);

word = buf[0] |
    (buf[1] << 8) |
    (buf[2] << 16) |
    (buf[3] << 24);

我同意你的代码有效是奇怪的,我原本预计Pickif建议的方法是必需的

如果它是依赖于编译器而不是与硬件有关并且与联合方法有关,则值得采用M Oehm提取位的建议

答案 1 :(得分:-1)

对于小端,你必须这样做

typedef union {
struct {
         unsigned int b24   : 1;
         unsigned int b25   : 1;
         unsigned int b26   : 1;
         unsigned int b27   : 1;
         unsigned int b28   : 1;
         unsigned int b29   : 1;
         unsigned int b30   : 1;
         unsigned int b31   : 1;
         unsigned int b32   : 1;

         unsigned int b16   : 1;
         unsigned int b17   : 1;
         unsigned int b18   : 1;
         unsigned int b19   : 1;
         unsigned int b20   : 1;
         unsigned int b21   : 1;
         unsigned int b22   : 1;
         unsigned int b23   : 1;
         unsigned int b24   : 1;

         /* etc. */

         unsigned int b08   : 1; /* LSB */
    } field;
    uint32_t word;
    int32_t integer;
} Bit32Field_T;