Eine Union ist eigentlich ein Konstrukt, um ein und denselben
Speicherplatz (nacheinander) für Objekte verschiedenen Typs nutzen zu
können. Wenn zum Beispiel eine Spalte einer Tabelle in unterschiedlichen
Zeilen Objekte unterschiedlichen Typs enthalten kann, kann man eine
Union nehmen ohne mit der Typprüfung des Compilers zu kollidieren. Die
Union garantiert dann, dass genug Speicher vorhanden ist, um ein Objekt
vom größten Type aufzunehmen. Die Alternative wären eine Spalte pro Type
(bzw. eine Spalte mit einer entsprechend große Struct) oder aufwändige
Casts.
Unions werden allerdings häufig benutzt, um ein Objekt eines Typs im
Speicher abzulegen (hier ein Struct von Chars) und als eine Objekt eines
andern Typs wieder auszulesen (hier ein Array von Chars). Sauber ist die
Sache aber nicht, denn der Standard sagt eindeutig, dass das Ergebnis
implementierungsabhängig ist. Auch wenn es meistens funktioniert darf
man sich also nicht wundern, wenn es, abhängig von Compiler und
Plattform, damit auch mal Probleme gibt.