C中的Bitfields和Unions给出了问题

时间:2012-11-21 12:18:58

标签: c struct unions bit-fields

我正在实施无线电标准,并且在结构和内存大小方面遇到了问题。在下面的例子中,我需要这个结构位于单个字节的内存中(按照无线电标准),但它目前给我2个字节的大小。经过多次挖掘,我明白这是因为联盟的规模"是字节而不是3位......但还没有解决这个问题。 我看过了:

但似乎都没有给我一个解决方案。

有什么想法吗?

谢谢!

#ifdef WIN32
#pragma pack(push)
#pragma pack(1)
#endif

typedef struct three_bit_struct
{
    unsigned char bit_a : 1;
    unsigned char bit_b : 1;
    unsigned char bit_c : 1;
}three_bit_struct_T;


typedef union
{
    three_bit_struct_T three_bit_struct;
    unsigned char another_three_bits : 3;
}weird_union_T;


typedef struct
{
    weird_union_T problem_union; 
    unsigned char another_bit : 1;
    unsigned char reserved : 4;
}my_structure_T;


int _tmain(int argc, _TCHAR* argv[])
{
     int size;

     size = sizeof(my_structure_T);

     return 0;
}


#ifdef WIN32
#pragma pack(pop)
#endif

2 个答案:

答案 0 :(得分:6)

问题是three_bit_struct_T的大小将四舍五入到最接近的字节 * ,而不管它在其位域中只包含三位。结构简单地不能具有部分字节的大小。因此,当您使用my_structure_T中的额外字段对其进行扩充时,不可避免地会将大小溢出到第二个字节中。

要将所有内容填充到单个字节中,您必须将所有位域成员放在外部my_structure_T中,而不是将它们作为内部结构/联合。

我认为你能做的最好就是将整个事情作为一个联盟。

typedef struct
{
    unsigned char bit_a : 1;
    unsigned char bit_b : 1;
    unsigned char bit_c : 1;
    unsigned char another_bit : 1;
    unsigned char reserved : 4;
} three_bit_struct_T;

typedef struct
{
    unsigned char another_three_bits : 3;
    unsigned char another_bit : 1;
    unsigned char reserved : 4;
} another_three_bit_struct_T;

typedef union
{
    three_bit_struct_T three_bit_struct;
    another_three_bit_struct_T another_three_bit_struct;
} my_union_T;

(*)或word,取决于对齐/打包设置。

答案 1 :(得分:0)

两个好的建议:从不在数据协议中使用struct / union,在任何情况下都可以使用never use bit-fields

实现这一点的最佳方法是通过位掩码和逐位运算符。

#define BYTE_BIT7 0x80u

uint8_t byte;

byte |= BYTE_BIT_7;  // set bit to 1
byte &= ~BYTE_BIT_7; // set bit to 0

if(byte & BYTE_BIT_7) // check bit value

此代码可移植到世界上的每个C编译器以及C ++。