Union of Structures - Page 1
Forum section: electronics / general

author: Ground_Loop
author_rank: Frequent Contributor
timestamp: October 21, 2020, 11:24:36 am
content: I'm having trouble understanding what is happening with the definition below:Code:#define U1MODE U1MODEextern volatile uint16_t U1MODE __attribute__((__sfr__));__extension__ typedef struct tagU1MODEBITS {union {struct {uint16_t STSEL:1;uint16_t PDSEL:2;uint16_t BRGH:1;uint16_t RXINV:1;uint16_t ABAUD:1;uint16_t LPBACK:1;uint16_t WAKE:1;uint16_t UEN:2;uint16_t :1;uint16_t RTSMD:1;uint16_t IREN:1;uint16_t USIDL:1;uint16_t :1;uint16_t UARTEN:1;};struct {uint16_t :1;uint16_t PDSEL0:1;uint16_t PDSEL1:1;uint16_t :5;uint16_t UEN0:1;uint16_t UEN1:1;};};} U1MODEBITS;extern volatile U1MODEBITS U1MODEbits __attribute__((__sfr__));I get unions, structures and attributes, but the two structures defined under the union baffles me. What is goin on here?

author: greenpossum
author_rank: Frequent Contributor
timestamp: October 21, 2020, 11:31:59 am
content: Bitfields.

author: Ground_Loop
author_rank: Frequent Contributor
timestamp: October 21, 2020, 11:34:16 am
content: Quote from: greenpossum on October 21, 2020, 11:31:59 amAnd I know what bit fields are. What is the purpose and usage of two structures

author: ledtester
author_rank: Super Contributor
timestamp: October 21, 2020, 11:39:24 am
content: You can access .PDSEL and get 2 bits or you can access .PDSEL0 and .PDSEL1 individually.Same with .UEN.

author: Ground_Loop
author_rank: Frequent Contributor
timestamp: October 21, 2020, 11:45:27 am
content: Quote from: ledtester on October 21, 2020, 11:39:24 amOk now I see the bit positions are the same for both structures. Thanks for that.

author: newbrain
author_rank: Super Contributor
timestamp: October 21, 2020, 11:58:04 am
content: Here, the use of unnamed nested structures and unions (standard since C11) allows to address the various field without the need of specifying a redundant structure or union object name.And bitfields, yes.Bitfields (even excluding the various __attribute__ __extension__ stuff used here) are very, very, very implementation dependent.Even the declaration as uint16_t is not exactly standard (allowed as an implementation dependent extension), as the standard only foresees int, (un)signed int and _Bool.Frankly, it makes no sense to me to declare the fields with a fixed size type (which is not taken into account at all).

author: Siwastaja
author_rank: Super Contributor
timestamp: October 21, 2020, 01:07:47 pm
content: Alternative ways of access. Really, really handy. For example, sometimes you want to access a memory location as a 32-bit operation, sometimes you want to assign or read part of it as a, say, 8-bit signed integer, or even more fancier, a 5-bit signed integer. Doing that using unions and bitfields results in more readable and less error prone code compared to a massive hack of bit masking and shifting.Sometimes different parts of documentation group configuration register bits differently. For example, STM32 SPI has a 16-bit transfer size register as an upper half of a control register. You may want to use the control register under the name given on the datasheet, but you may also want to access SPI->TSIZE = 42; for convenience and clarity.Another good example would be reading 57 bytes of calibration data out of a device: you just want to access them as calib.u8 or calib.u32 depending on the communication data width available; but after the readout, you want to access it using calib.voltage_offset or whatever.Anonymous structs inside union are great because you don't need to access thing.done_one_way.blargh and thing.done_another_way.blorgh, just using thing.blargh and thing.blorgh is enough.Initializers get a bit tricky, though, you need quite some extra {{{}}}.Do note that with bitfields, you rely on particular compiler putting them in particular order, possibly with no proper attributes to control the order available. Further limiting yourself to not using bitfields allows almost portable solution given that any decent compiler have had the concept of packed struct for a long time. The syntax for giving that attribute varies compiler to compiler, but you can #define that out for simple porting.A pedantic note is worth mentioning: C standard at least originally - I haven't looked if this has been fixed - said that union cannot be used for such purpose; by writing one element in the union, you are supposed to only read the same element back, not access the same data through the another element; only rendering the union useful for memory saving of static objects, pretty useless. In practice, this is meaningless; everybody uses unions in the "forbidden" way because that's actually very useful, and any decent compiler works correctly (if it doesn't, and if it's being maintained, it will get fixed due to widespread usage of union).As a general note, sometimes on microcontrollers, the actual memory access instruction width matters. You may really NEED to read or write a 8-bit AHB/APB bus operation, instead of writing the full 32-bit register, or even worse, read-modify-write.

author: newbrain
author_rank: Super Contributor
timestamp: October 21, 2020, 01:48:29 pm
content: Quote from: Siwastaja on October 21, 2020, 01:07:47 pmI just did a very similar thing for reading/writing part of configuration and status of an RTC through I2C in a clearer manner.And about the standards:Something did change between ISO/IEC 9899:1999 and ISO/IEC 9899:2011.'6.2.6 Representations of types' is unchanged.For both, an array of unsigned is guaranteed to never to be a trap representation, so it's always possible to read the object representation as a sequence of "bytes".In C11 this footnote in '6.5.2.3, Structure and union members' has been added:QuoteI read this as condoning type punning, if one can guarantee never to incur in a trap representation.This guarantee can sometimes be inferred by other constraints on the involved types.C18 (aka C17), ISO/IEC 9899:2018, does not change in this respect.

author: Ground_Loop
author_rank: Frequent Contributor
timestamp: October 22, 2020, 02:07:11 am
content: Thanks guys it's clear now. This helps a lot.