Why do we need C Unions? Why do we need C Unions? c c

Why do we need C Unions?


Unions are often used to convert between the binary representations of integers and floats:

union{  int i;  float f;} u;// Convert floating-point bits to integer:u.f = 3.14159f;printf("As integer: %08x\n", u.i);

Although this is technically undefined behavior according to the C standard (you're only supposed to read the field which was most recently written), it will act in a well-defined manner in virtually any compiler.

Unions are also sometimes used to implement pseudo-polymorphism in C, by giving a structure some tag indicating what type of object it contains, and then unioning the possible types together:

enum Type { INTS, FLOATS, DOUBLE };struct S{  Type s_type;  union  {    int s_ints[2];    float s_floats[2];    double s_double;  };};void do_something(struct S *s){  switch(s->s_type)  {    case INTS:  // do something with s->s_ints      break;    case FLOATS:  // do something with s->s_floats      break;    case DOUBLE:  // do something with s->s_double      break;  }}

This allows the size of struct S to be only 12 bytes, instead of 28.


Unions are particularly useful in Embedded programming or in situations where direct access to the hardware/memory is needed. Here is a trivial example:

typedef union{    struct {        unsigned char byte1;        unsigned char byte2;        unsigned char byte3;        unsigned char byte4;    } bytes;    unsigned int dword;} HW_Register;HW_Register reg;

Then you can access the reg as follows:

reg.dword = 0x12345678;reg.bytes.byte3 = 4;

Endianness (byte order) and processor architecture are of course important.

Another useful feature is the bit modifier:

typedef union{    struct {        unsigned char b1:1;        unsigned char b2:1;        unsigned char b3:1;        unsigned char b4:1;        unsigned char reserved:4;    } bits;    unsigned char byte;} HW_RegisterB;HW_RegisterB reg;

With this code you can access directly a single bit in the register/memory address:

x = reg.bits.b2;


Low level system programming is a reasonable example.

IIRC, I've used unions to breakdown hardware registers into the component bits. So, you can access an 8-bit register (as it was, in the day I did this ;-) into the component bits.

(I forget the exact syntax but...) This structure would allow a control register to be accessed as a control_byte or via the individual bits. It would be important to ensure the bits map on to the correct register bits for a given endianness.

typedef union {    unsigned char control_byte;    struct {        unsigned int nibble  : 4;        unsigned int nmi     : 1;        unsigned int enabled : 1;        unsigned int fired   : 1;        unsigned int control : 1;    };} ControlRegister;