Reputation: 1132
I want to declare a union
in C which mainly contains a 16-bit
word, and I should be able to read/write the LSP 7 bits
and 8th bit
separately for each byte in the 16-bit
word, so I declared something like:
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;
Now, when I write 7-bit
values to these individual bytes in the 16-bit
word:
x.full_8_char_byte[0] = 0x7E;
x.full_8_char_byte[1] = 0x7E;
The following simple program:
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;
}
gives the correct output as follows:
~ ~
126 126
7E 7E
~ ~
126 126
7E 7E
0 0
but when I initialized 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;
the output I get is:
� ~
255 126
FF 7E
~ ~
126 126
7E 7E
0 0
Similar thing happens when I initialize x.full_8_char_byte[0] to 0xFF
, my question is why the value in x.ascii_7_bits_word_1
and x.parity_bit_word_1
did not reflected per change in x.full_8_char_byte[1]
?
Upvotes: 2
Views: 590
Reputation:
Looking at this:
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;
The comments suggest you expect the 4 bitfield members to map the bits of the first array member. That won't work, because all members of a union
are alternative possible contents, which also means every member will be placed at the very beginning. What you probably meant to write instead is
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;
So this union can either contain your array or a struct with bitfields.
Note that this doesn't solve your problem in a portable way: There are no strict guarantees about how your bitfield will be arranged, see Leushenko's comment for details! For solving this problem portably, you can for example provide macros to access the individual bits, e.g.
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)
Or, if you also need to write to the bits or want to enforce type safety, write (inline) functions instead.
Upvotes: 5