Una struttura non è nient'altro che un record: la sua dimensione in memoria equivale alla somma delle dimensioni di ciascun suo campo.
Esempio:
codice:
struct miorecord {
char nome[20];
char cognome[20];
int eta;
}
Questa struttura occupa 44 byte (supponendo un intero di 4 byte)
La Union è, invece, il raggruppamento di tante componenti nella minima unità di memoria in grado di contenerle.
Esempio:
codice:
union miaunion {
int valore;
char primobyte;
char secondobyte;
char terzobyte;
char quartobyte;
}
Questa union occupa esattamente 4 byte (supponendo, sempre, un intero di 4 byte)
Nell'ultimo esempio le quattro variabili char rappresentano, ciascuna, un byte dell'intero: in questo modo è possibile avere in memoria una variabile di tipo intero e riuscire ad indirizzare ciascun byte di quella variabile in modo indipendente. E' molto utile, questo tipo di dato, quando si devono analizzare dei flag: supponiamo di avere una variabile char (che occupa un byte) che rappresenta una serie di 8 flag che controllano una determinata periferica. Avendo a disposizione una struttura, che mi rappresenta un campo di bit, ed una union io posso analizzare il byte ricevuto dalla periferica per sapere se un determinato bit è settato o meno. Ecco come:
codice:
struct campobit {
unsigned a7 : 1;
unsigned a6 : 1;
unsigned a5 : 1;
unsigned a4 : 1;
unsigned a3 : 1;
unsigned a2 : 1;
unsigned a1 : 1;
unsigned a0 : 1;
};
union mioflag {
struct campobit campo;
char bytericevuto;
};
...
mioflag flg;
flg.bytericevuto = get_da_periferica(); // ottengo il byte dalla periferica
// controllo il 4° bit
if (flg.campo.a3) {
// il bit è settato
} else {
// il bit non è settato
}
Ecco quello che c'è in memoria:
|---------------------------------------|
| a7 | a6 | a5 | a4 | a3 | a2 | a1 | a0 |
|------------- bytericevuto ------------|
Spero di averti aiutato a comprendere le potenzialità offerte da questi due tipi di dato (combinandoli, anche).
Ciao.