Search code examples
cstructunions

structs and referring to them two different ways


I am reading someone's code I do not understand why he is referencing inside each union below differently.

-On the first one, he is able to reference inside by typing pwr_cmd.EN1 -On the second one, he is able to reference inside by typing errors.Bits.ERR1 -If I remove the Bits from the second one, will I be able to reference inside the the same way as the first one: errors.ERR1? -What is the difference between the two and why would you do one over the other? Thank you.

typedef union {
    byte Byte;
    union {
        struct {
            byte EN1 :1;
            byte EN2 :1;
            byte EN3 :1;
            byte EN4 :1;
            byte :4;
        };
        struct {
            byte :2;
            byte EN34 :2;
            byte :4;
        };
        struct {
            byte :2;
            byte EN3r:1;
            byte EN4r:1;
            byte :4;
        };

    };
} pwr_cmd;



typedef union {
    word Word;
    union {
        struct {
            byte ERR1 :1;
            byte ERR2 :1;
            byte ERR3 :1;
            byte ERR4 :1;
            byte ERR5 :1;
            byte ERR6 :1;
            byte ERR7 :1;
            byte ERR8 :1;
            byte ERR9 :1;
            byte DET1 :1;
            byte DET2 :1;
            byte FAIL1 :1;
            byte PWR1 :1;
            byte PWR2 :1;
            byte PWR3 :1;
            byte PWR4 :1;
        } Bits;
            nibble4 Nibble4;
    };
} errors;

Solution

  • This is an example of a bitfield - each variable with a ":" represents a certain number of bits of an integer. This bitfield is unionized to allow the same bit positions to be named differently depending on context.

    You would access one union member over another for clarity and to denote the intention of your code - this is a good way to self-document code, by creating meaningful names instead of something meaningless like "bit 4".

    Re-reading your question - the difference between the two is that one uses named structs and the other doesn't. In the first, the members of the structs can be accessed without doing a struct member reference ("."), because they have no name. In the second, he declares a struct with a name, so the struct member reference is used. In my opinion the second is more clear, but the first is more concise. It's a matter of style and preference.