struct Variant { enum { INT, FLOAT, STR } tag; // who lives in the room now? union { int i; float f; char *s; } val;};
WHY: there is no runtime flag inside a union telling you the active member. The tag is your bookkeeping so you only read what you last wrote.
Recall Feynman: explain to a 12-year-old
Imagine one whiteboard. You can write a number, OR a word, OR a drawing — but only one thing fits because it's the same board. If you write a word over your number, the number is gone. A union is that single whiteboard shared by different kinds of "writing." A struct, by contrast, is a notebook with a separate page for each thing. The board is exactly as big as the biggest thing you might write.
Dekho, union ka matlab simple hai: ek hi memory ka tukda jise saare members share karte hain. struct mein har member ka apna alag ghar hota hai (isliye size = sab members ka sum), lekin union mein sab roommates ek hi kamre mein rehte hain — sabhi offset 0 se start hote hain. Isliye union ka size hamesha uske sabse bade member ke barabar hota hai (alignment padding ke saath).
Sabse important baat: ek time pe sirf ek member valid hota hai. Jab tum d.f = 3.14 likhte ho, to wahi bytes overwrite ho jaate hain, aur agar tum phir d.i padho to garbage milega — kyunki ab un bytes mein float ka bit pattern pada hai, int ka nahi. Ye koi conversion nahi hota, sirf same bytes ko alag tarah se "padhna" hai (isko type punning kehte hain).
Ek bahut common galti: log sochte hain d.i = 65 ke baad d.f padhne se 65.0 milega. Galat! Bits same hote hain par interpretation alag — int 65 aur float 65.0 ke bit patterns bilkul alag hote hain. Value convert karni ho to (float)d.i cast karo.
Real life mein union ka use memory bachane ke liye aur tagged union banane ke liye hota hai — ek struct mein union + ek enum "tag" rakho jo bataye abhi kaunsa member active hai, kyunki union khud kuch yaad nahi rakhta. Bas yahi core idea hai: ek room, ek waqt mein ek hi cheez, size = sabse bada member.