ProgrammatieEmbedded/Low-level C ontwikkelaar

Leg uit hoe unions in de C-taal werken. Welke taken worden ermee opgelost, hoe gebruik je ze correct en welke typische valkuilen komen voor bij het gebruik ervan?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Union (uniegroep) is een speciaal datatype dat verschillende waarden in hetzelfde geheugen opslaat. In een union bevinden alle leden zich op hetzelfde geheugenadres, en de hoeveelheid geheugen is gelijk aan de grootte van het grootste lid.

Gebruik:

  • handig om geheugen te besparen wanneer een variabele op een bepaald moment één van verschillende typen waarden kan aannemen;
  • stelt je in staat om dezelfde bits op verschillende manieren te interpreteren (bijvoorbeeld voor low-level toegang of protocollen).

Voorbeeld:

union Data { int i; float f; char s[4]; }; union Data d; d.i = 0x41424344; // nu zijn er 4 bytes in het geheugen, die als int, float of string gelezen kunnen worden printf("%c%c%c ", d.s[0], d.s[1], d.s[2]); // vendor-specifieke output

Valkuilen en gebruiksregels:

  • Houd in de union op elk moment slechts één "significant" veld.
  • Er is geen automatische tracking van welk veld als "actief" laatste was.
  • Lezen van een niet-actief veld — onbepaald gedrag.
  • De bytevolgorde op het platform is zeer belangrijk (endian!)

Zwaluwvraag

Vraag: Wat is de zin van het gebruik van een union, wanneer je gewoon een structuur met meerdere velden kunt gebruiken?

Antwoord: Het gebruik van een union bespaart geheugen, omdat op elk moment slechts ÉÉN waarde intern wordt opgeslagen, en niet allemaal tegelijk. In een structuur wordt geheugen voor elk veld toegewezen, terwijl in een union alleen voor het grootste veld geheugen wordt gereserveerd, de andere "delen" dit geheugen. Bovendien stelt een union je in staat om veilige of opzettelijke omzettingen tussen verschillende datatypes in hetzelfde geheugensegment uit te voeren.

Voorbeeld:

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))

Voorbeelden van echte fouten


Verhaal

In een apparaatdriverproject werd de verbinding met de hardware via een union met bit-toegang tot gegevens gedaan. Na een kleine refactor begon de ontwikkelaar in een verkeerd union-veld te schrijven, wat leidde tot het lezen van verouderde gegevens en fatale systeemfouten, omdat in de union op elk moment slechts één veld "actueel" is.


Verhaal

Bij het uitwisselen van netwerkpakketten via een union voor geheugensynchronisatie vergat de ontwikkelaar de structurering van de structuren in overweging te nemen. Dit resulteerde in een verschuiving van één byte, en de struct werd met onjuiste offsetten geparsed, wat het protocol incompatibel maakte met het origineel.


Verhaal

Bij het werken aan een serialisatiebibliotheek droeg de programmeur de union als waarde over naar een functie, waar het benodigde veld niet werd geïnitialiseerd voordat het werd gelezen. Dit leidde tot onjuiste serialisatie van de gegevens, wat resulteerde in rommel in de uitvoerstream en het onmogelijk maken om de oorspronkelijke informatie te herstellen.