Forskjellen mellom en struktur og en union

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å?

Løsning

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.

Kommentarer (12)

"union" og "struct" er konstruksjoner i C-språket. Å snakke om en forskjell på "OS-nivå" mellom dem er upassende, siden det er kompilatoren som produserer forskjellig kode om du bruker det ene eller det andre nøkkelordet.

Kommentarer (0)

En struktur allokerer den totale størrelsen på alle elementene i den.

En union allokerer bare så mye minne som det største medlemmet krever.

Kommentarer (1)