Union (unione) è un tipo di dato speciale che memorizza valori diversi nella stessa area di memoria. In un union tutti i membri occupano la stessa posizione in memoria e la dimensione della memoria è pari alla dimensione del membro più grande.
Utilizzo:
Esempio:
union Data { int i; float f; char s[4]; }; union Data d; d.i = 0x41424344; // ora in memoria ci sono 4 byte che possono essere letti come int, float, stringa printf("%c%c%c\n", d.s[0], d.s[1], d.s[2]); // output specifico del vendor
Insidie e regole d'uso:
Domanda: Qual è il senso di usare union quando si può semplicemente usare una struttura con più campi?
Risposta: Usare union risparmia memoria, perché in qualsiasi momento contiene solo UN valore, non tutti contemporaneamente. In una struttura, per ogni campo viene riservata memoria, mentre in un union solo per il campo massimo, gli altri "condividono" questa memoria. Inoltre, l'union consente di eseguire una conversione sicura o intenzionale tra diverse rappresentazioni di dati su un frammento di memoria.
Esempio:
struct S { int i; float f; } s; // sizeof = sizeof(int) + sizeof(float) union U { int i; float f; } u; // sizeof = max(sizeof(int),sizeof(float))
Storia
In un progetto di driver di dispositivo, la comunicazione con l'hardware avveniva tramite union con accesso bit ai dati. Dopo una piccola rifattorizzazione, lo sviluppatore ha iniziato a scrivere nel campo sbagliato dell'union, il che ha portato alla lettura di dati non validi e a gravi guasti di sistema, poiché nell'union solo un campo è "reale" in ogni momento.
Storia
Durante lo scambio di pacchetti di rete tramite union per la gestione della memoria, lo sviluppatore ha dimenticato di considerare l'allineamento delle strutture. Di conseguenza, si è verificato uno spostamento di un byte e la struttura è stata analizzata con spostamenti errati, rendendo il protocollo incompatibile con l'originale.
Storia
Lavorando su una libreria di serializzazione, il programmatore ha passato un union per valore a una funzione, dove il campo necessario non è stato inizializzato prima della lettura. Questo ha causato una serializzazione errata dei dati, con spazzatura nel flusso di output, e ripristinare le informazioni originali è stato impossibile.