Unions are pure first-principles: bits are bits, and you’re the one giving them meaning. Memory is just a sequence of bytes divided into slots.

From this ground truth, a C++ union is as a single slot—say, 4 bytes—that can wear different hats: union Data { int i; float f; char c; }; lets you store an int, a float, or a char in that one spot. Set f = 3.14, and those bytes (0x4048F5C3) are written on memory. It’s sized for the largest stored value (float), and you decide what’s active, no hand-holding from the compiler. If you overwrite `f withint i = 3`. The value in the union is mutated and you have to manually keep a track of these mutations. *Avoid 'naked’ unions; wrap them in a class together with a type field;

Compare this to a struct: it’s a wardrobe with a slot per item—an int slot, a float slot, a char slot—each with its own space (e.g., 9 bytes total for struct Data { int i; float f; char c; };).

1
2
3
4
union Data { int i; float f; char c; }; //one 4-byte chunk (sized for float)
Data d; d.i = 42; printf("%d\n", d.i); // 42
d.f = 3.14; printf("%f\n", d.f); // f overwrites i
enum { INT, FLOAT, CHAR } type; type = FLOAT; // you decide what’s live.