Finnes det noe godt eksempel på forskjellen mellom en struct
og en union
?
I utgangspunktet vet jeg at struct
bruker alt minnet til sitt medlem og union
bruker det største medlemmets minneplass. Er det noen annen forskjell på OS-nivå?
Med en union skal du bare bruke ett av elementene, fordi de alle er lagret på samme sted. Dette er nyttig når du vil lagre noe som kan være av flere typer. En struct, derimot, har en egen minneplassering for hvert av elementene, og alle kan brukes samtidig.
For å gi et konkret eksempel på hvordan de kan brukes, jobbet jeg for en stund siden med en Scheme-tolk og la Scheme-datatypene over C-datatypene. Dette innebar at jeg i en struct lagret en enum som angir typen verdi, og en union for å lagre denne verdien.
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
edit: Hvis du lurer på hva det å sette x.b til 'c' endrer verdien av x.a til, er det teknisk sett udefinert. På de fleste moderne maskiner er en char 1 byte og en int 4 byte, så hvis du gir x.b verdien 'c', får også den første byten i x.a samme verdi:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
utskrifter
99, 99
Hvorfor er de to verdiene like? Fordi de tre siste byte i int 3 alle er null, slik at den også leses som 99. Hvis vi legger inn et større tall for x.a, vil du se at dette ikke alltid er tilfelle:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
utskrifter
387427, 99
For å se nærmere på de faktiske minneverdiene kan vi angi og skrive ut verdiene i hex:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
skriver ut
deadbe22, 22
Du kan tydelig se hvor 0x22 overskrev 0xEF.
**MEN
I C er rekkefølgen på byte i en int ikke definert. Dette programmet overskrev 0xEF med 0x22 på min Mac, men det finnes andre plattformer der det ville overskrive 0xDE i stedet fordi rekkefølgen på byte som utgjør int er omvendt. Når du skriver et program, bør du derfor aldri stole på overskriving av spesifikke data i en union, fordi det ikke er portabelt.
Hvis du vil lese mer om rekkefølgen på byte, kan du ta en titt på endianness.