Is it valid to use bit fields with union?
Asked Answered
G

3

21

I have used bit field with a structure like this,

struct
{
       unsigned int is_static: 1;
       unsigned int is_extern: 1;
       unsigned int is_auto: 1;
} flags;

Now i wondered to see if this can be done with a union so i modified the code like,

union
{
       unsigned int is_static: 1;
       unsigned int is_extern: 1;
       unsigned int is_auto: 1;
} flags;

I found the bit field with union works but all those fields in the union are given to a single bit as I understood from output. Now I am seeing it is not erroneous to use bit fields with union, but it seems to me that using it like this is not operationally correct. So what is the answer - is it valid to use bit field with union?

Glob answered 4/7, 2012 at 9:41 Comment(1)
Please, what does not operate correctly?Glenn
T
4

You are given a gun and bullets. Is it okay to shoot your self in foot with it? Of course not, but nobody can stop you from doing this if you want to.

My point is, just like gun and bullets, union and bit fields are tools and they have their purpose, uses and "abuses". So using bitfields in union, as you have written above, is perfectly valid C but a useless piece of code. All the fields inside union share same memory so all the bitfields you mention are essentially same flag as they share same memory.

Taipan answered 4/7, 2012 at 9:54 Comment(2)
This metaphor is far more useless than the code in the OP's question.Edessa
Plenty useful if the bits can mean different things at different times, as is the case for hardware registers on microcontrollers. This can also be found frequently in file formats as a way to save space by cramming different types of data into one array and having a flag that tells the type of each element. SO really has a problem with people thinking they know everything about how language feature should be used, based on their limited personal experience.Carnauba
O
42

It is valid but as you found out, not useful the way you have done it there.

You might do something like this so you can reset all the bits at the same time using flags.

union {
    struct {
        unsigned int is_static: 1;
        unsigned int is_extern: 1;
        unsigned int is_auto: 1;
    };
    unsigned int flags;
};

Or you might do something like this:

union {
    struct {
        unsigned int is_static: 1;
        unsigned int is_extern: 1;
        unsigned int is_auto: 1;
    };
    struct {
        unsigned int is_ready: 1;
        unsigned int is_done: 1;
        unsigned int is_waiting: 1;
    };
};
Opener answered 4/7, 2012 at 9:55 Comment(1)
I have added some semicolons assuming you wanted anonymous structures. Also note that they're not standard C. In gcc, you have to use -fms-extensions for these to work.Invar
T
4

You are given a gun and bullets. Is it okay to shoot your self in foot with it? Of course not, but nobody can stop you from doing this if you want to.

My point is, just like gun and bullets, union and bit fields are tools and they have their purpose, uses and "abuses". So using bitfields in union, as you have written above, is perfectly valid C but a useless piece of code. All the fields inside union share same memory so all the bitfields you mention are essentially same flag as they share same memory.

Taipan answered 4/7, 2012 at 9:54 Comment(2)
This metaphor is far more useless than the code in the OP's question.Edessa
Plenty useful if the bits can mean different things at different times, as is the case for hardware registers on microcontrollers. This can also be found frequently in file formats as a way to save space by cramming different types of data into one array and having a flag that tells the type of each element. SO really has a problem with people thinking they know everything about how language feature should be used, based on their limited personal experience.Carnauba
C
4

Here is an example on how to use bit fields with unions. I'm also showing how to arrange for MSB. In pictures it would look something like this:

 MSB        LSB
 7            0
+------+-------+
| five | three |
| bits | bits  |
+------+-------+

// A struct tag definition of 
// two bit fields in an 8-bit register
struct fields_tag {
   // LSB
   unsigned int five:5;
   unsigned int three:3;
   // MSB
};

// here is a tag and typedef for less typing
// to modify the 8-bit value as a whole
// and read in parts.
typedef union some_reg_tag {
    uint8_t raw;
    struct fields_tag fields;
} some_reg_t;

Here is how to use the bit fields with Arduino

some_reg_t a_register;
a_register.raw = 0xC2;  // assign using raw field.

Serial.print("some reg = ");  // dump entire register
Serial.println(a_register.raw, HEX);   // dump register by field
Serial.print("some reg.three = ");
Serial.println(a_register.fields.three, HEX);
Serial.print("some reg.five = ");
Serial.println(a_register.fields.five, HEX);

Here is the output showing the results

some reg = C2
some reg.three = 6
some reg.five = 2
Consols answered 4/10, 2021 at 17:59 Comment(2)
<a href='stackoverflow.com/users/5352316/trist'>TrisT</a> Tell me about it. Someone just downvoted my answer here showing the OP how to do just that. Gotta love SO.Consols
But consider that it is not guaranteed that your 5+3 bits will be packed into one byte! See https://mcmap.net/q/563811/-are-there-reasons-to-avoid-bit-field-structure-members or "Adjacent bit-field members may (or may not) be packed to share and straddle the individual bytes.", en.cppreference.com/w/cpp/language/bit_field. Or that "The standard states that reading from any union member other than the last one written to results in undefined behavior", cboard.cprogramming.com/cplusplus-programming/….Ripon

© 2022 - 2024 — McMap. All rights reserved.