提取C中16位并集的位位置

时间:2018-07-25 07:41:38

标签: c unions

我想在C中声明一个union,主要包含一个16-bit字,并且我应该能够读/写 LSP 7 bits8th bit字中的每个字节分别16-bit,所以我声明了类似的内容:

typedef union {
    uint8_t full_8_char_byte[2];
    uint8_t ascii_7_bits_word_0 : 7; /* another way of representing LSP 7 ASCII bits */
    uint8_t parity_bit_word_0 : 1;   /* another way of representing MSP parity bit */
    uint8_t ascii_7_bits_word_1 : 7; /* another way of representing LSP 7 ASCII bits */
    uint8_t parity_bit_word_1 : 1;   /* another way of representing MSP parity bit */
} ip_char_t;

现在,当我将7-bit值写入16-bit字中的这些单个字节时:

x.full_8_char_byte[0] = 0x7E;
x.full_8_char_byte[1] = 0x7E;

以下简单程序:

int main()
{
    ip_char_t x;
    x.full_8_char_byte[0] = 0x7E;
    x.full_8_char_byte[1] = 0x7E;

    printf("%c   %c\n", x.full_8_char_byte[1], x.full_8_char_byte[0]);
    printf("%u   %u\n", x.full_8_char_byte[1], x.full_8_char_byte[0]);
    printf("%X   %X\n\n", x.full_8_char_byte[1], x.full_8_char_byte[0]);

    printf("%c   %c\n", x.ascii_7_bits_word_1, x.ascii_7_bits_word_0);
    printf("%u   %u\n", x.ascii_7_bits_word_1, x.ascii_7_bits_word_0);
    printf("%X   %X\n\n", x.ascii_7_bits_word_1, x.ascii_7_bits_word_0);

    printf("%d   %d\n", x.parity_bit_word_1, x.parity_bit_word_0);
    return 0;
}

给出正确的输出,如下所示:

~   ~  
126   126   
7E   7E

~   ~ 
126   126 
7E   7E

0   0

但是当我初始化x.full_8_char_byte[1] to a 8-bit value时:

x.full_8_char_byte[0] = 0x7E;
x.full_8_char_byte[1] = 0xFF;

我得到的输出是:

�   ~ 
255   126 
FF   7E

~   ~ 
126   126 
7E   7E

0   0

类似的事情在我初始化x.full_8_char_byte[0] to 0xFF时发生了,我的问题是为什么x.ascii_7_bits_word_1x.parity_bit_word_1中的值没有反映出x.full_8_char_byte[1]的每次更改?

1 个答案:

答案 0 :(得分:4)

看这个:

typedef union {
    uint8_t full_8_char_byte[2];
    uint8_t ascii_7_bits_word_0 : 7; /* another way of representing LSP 7 ASCII bits */
    uint8_t parity_bit_word_0 : 1;   /* another way of representing MSP parity bit */
    uint8_t ascii_7_bits_word_1 : 7; /* another way of representing LSP 7 ASCII bits */
    uint8_t parity_bit_word_1 : 1;   /* another way of representing MSP parity bit */
} ip_char_t;

注释建议您期望4位字段成员映射第一个数组成员的位。这是行不通的,因为union所有成员是可能的替代内容,这也意味着每个成员都将放在最开始的位置。您可能打算写的是

typedef union {
    uint8_t full_8_char_byte[2];
    struct {
        uint8_t ascii_7_bits_word_0 : 7; /* another way of representing LSP 7 ASCII bits */
        uint8_t parity_bit_word_0 : 1;   /* another way of representing MSP parity bit */
        uint8_t ascii_7_bits_word_1 : 7; /* another way of representing LSP 7 ASCII bits */
        uint8_t parity_bit_word_1 : 1;   /* another way of representing MSP parity bit */
    };
} ip_char_t;

因此,此联合可以 包含数组具有位域的结构。


请注意,这不能以便携式方式解决您的问题:对于位域的排列方式没有严格的保证,有关详细信息,请参阅Leushenko的评论!为了可移植地解决此问题,例如,您可以提供宏来访问各个位,例如

typedef uint8_t ip_char_t[2];

#define ascii_7_bits_word(x,i) ((x)[i] & 0x7f)
#define parity_bit_word(x,i) ((x)[i] >> 7)

或者,如果您还需要写入这些位或想要加强类型安全性,请改为编写(内联)函数。