ProgrammatieEmbedded ontwikkelaar, Backend ontwikkelaar

Leg de structuur en werking van de voorwaardelijke operator (ternaire operator) in C uit. Welke valkuilen zijn er met betrekking tot typeconversies en neveneffecten die zich voordoen bij het gebruik ervan?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

De ternaire voorwaardelijke operator (?:) maakt het mogelijk om een van de twee expressies te berekenen en retourneren op basis van een voorwaarde:

result = cond ? expr_true : expr_false;
  • Type van het resultaat wordt bepaald volgens de algemene regels voor "gebruikelijke aritmetische conversies" (als beide expressies cijfers zijn) of op basis van het type van de grootste operand (voor pointers en structuren).
  • Beide expressies moeten compatibel zijn qua type. Als ze van verschillende types zijn, zal de compiler proberen ze naar een gemeenschappelijk type om te zetten, soms met onverwachte resultaten of dataverlies.
  • De ternaire operator staat neveneffecten toe in beide expressies, maar alleen de benodigde wordt geëvalueerd op basis van de voorwaarde.
  • Bij complexe expressies ontstaan problemen met dubbelzinnigheid of onvoorspelbaar gedrag (vooral bij geneste expressies of gebruik met macro's en functies).

Voorbeeld

int a = 10, b = 0; int max = (a > b) ? a : b; // max = 10

Vragend met een valkuil

"Als twee expressies van de ternaire operator objecten van verschillende types retourneren (bijvoorbeeld een pointer en nul), wat is dan het type van het resultaat?"

Velen beweren dat de compiler altijd het type resultaat "raad". In werkelijkheid, als een van de expressies een pointer is en de andere 0 of NULL, dan heeft het resultaat het type van de pointer. Als het verschil complexer is — bijvoorbeeld, een pointer van een ander type of een int en een enum type — kan er onopgemerkt dataverlies optreden, en soms geeft de compiler een foutmelding.

struct node *p = NULL; void *v = cond ? p : NULL; // ok void *z = cond ? p : 0; // ok int i = cond ? 0 : "abc"; // fout: incompatibele types

Voorbeelden van echte fouten door onwetendheid van de nuances van het onderwerp


Verhaal

In een groot project met cross-compilatie produceerde de gebruikte expressie cond ? ptr : 0 een pointer met de ene compiler en een int met de andere (waarbij 0 strikt als int werd geïnterpreteerd). Het systeem faalde bij de poging om het resultaat als pointer te gebruiken.


Verhaal

In een financieel pakket, waar de retourfuncties de ternaire operator met "blote" literalen gebruikten (cond ? 0.0 : 1), werd het resultaattype per ongeluk double, terwijl int werd verwacht, wat leidde tot vergelijkings- en afdrukfouten.


Verhaal

In een van de bibliotheken werd een aanroep gedaan met een expressie met een neveneffect: flag ? inc(x) : dec(x). Bij het refactoren ontdekte men een verborgen fout: beide expressies riepen de functie aan (met hun eigen side-effects), terwijl men verwachtte dat er maar één zou worden uitgevoerd. De verwarring met geneste macro's leidde tot dubbele wijziging van de waarde, wat pas tijdens gedetailleerd testen werd ontdekt.