在 C 中提取 16 位联合中的位位置
Extracting bit positions in a union of 16 bits in C
我想在C中声明一个union
,主要包含一个16-bit
字,我应该可以read/write LSP 7 bits
和 8th 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_1
和 x.parity_bit_word_1
中的值没有反映在 x.full_8_char_byte[1]
中的每个变化?
看着这个:
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
的 all 成员是可选的可能内容,这也意味着每个成员都将放在最开始。你可能想写的是
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)
或者,如果您还需要写入位或想要强制执行类型安全,请改为编写(内联)函数。
我想在C中声明一个union
,主要包含一个16-bit
字,我应该可以read/write LSP 7 bits
和 8th 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_1
和 x.parity_bit_word_1
中的值没有反映在 x.full_8_char_byte[1]
中的每个变化?
看着这个:
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
的 all 成员是可选的可能内容,这也意味着每个成员都将放在最开始。你可能想写的是
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)
或者,如果您还需要写入位或想要强制执行类型安全,请改为编写(内联)函数。