ProgrammatieC softwareontwikkelaar

Hoe wordt de initialisatie van structuren in C geïmplementeerd? Praat over de verschillende manieren van initialisatie, de volgorde van initialisatie van velden, partiële initialisatie, en welke valkuilen er kunnen ontstaan bij het werken met geneste structuren en het ontbreken van enkele initialisatoren.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In C zijn er verschillende manieren om structuren te initialiseren:

  1. Standaardinitialisatie (op volgorde):
struct Point { int x, y; }; struct Point p = {10, 20};

De velden worden geïnitialiseerd in de aangegeven volgorde.

  1. Initialisatie met benoemde velden (C99+):
struct Point p = {.y = 20, .x = 10};

Velden kunnen in elke volgorde worden geïnitieerd.

  1. Partiële initialisatie: Als niet alle velden expliciet zijn opgegeven, worden de overige automatisch geïnitialiseerd op nullen.
struct Rect { int x, y, w, h; } r = {1, 2}; // w en h == 0
  1. Geneste structuren: De initialisatie van geneste structuren vereist een opeenvolgende (of benoemde) specificatie van alle geneste waarden.
struct Color { int r, g, b; }; struct Pixel { struct Point pos; struct Color col; }; struct Pixel px = {{10,20}, {255,0,0}};

Benoemde initialisatie helpt om fouten te voorkomen:

struct Pixel px = {.col = {.r = 255, .g = 0, .b = 0}};

Valkuilen:

  • Het is gemakkelijk om een fout te maken in de volgorde van velden bij op volgorde gebaseerde initialisatie.
  • Partiële initialisatie is niet altijd veilig voor structuren die geneste pointers bevatten — in dat geval worden niet-geïnitialiseerde pointers alleen NULL als ze expliciet worden geïnitialiseerd of als de structuur een statische/globale opslaglocatie heeft.
  • Als het type is veranderd (bijvoorbeeld, als er een nieuw veld aan het begin van de structuur is toegevoegd), kan de oude initialisatie leiden tot onverwachte resultaten.

Misleidende vraag

Vraag: Wat gebeurt er als niet alle velden van een structuur expliciet worden opgegeven bij de initialisatie, en de structuur is gedefinieerd als een automatische lokale variabele?

Verwacht foutief antwoord: "De resterende velden zijn altijd gelijk aan null."

Correct antwoord: Automatische (lokale) variabelen, die niet expliciet zijn geïnitialiseerd, blijven met niet-geïnitialiseerde waarden. Partiële initialisatie initialiseert alleen de expliciet opgegeven velden, de rest heeft onbepaalde waarde (tenzij geïnitialiseerd via = {...}, waar de rest alleen nullen zal zijn voor statische/globale structuren).

Voorbeeld:

void foo() { struct Point { int x, y, z; } p = {1}; // p.x == 1, p.y en p.z == 0 (Alleen via = {1};) }

Voorbeelden van echte fouten door gebrek aan kennis van de subtiliteiten van het onderwerp


Verhaal

In een grafische engine werd een veld aan het begin van de structuur van een vertex toegevoegd, zonder de algemene manier van initialisatie van objecten in verschillende modules te herzien. Als gevolg daarvan begon de helft van de modules de kleur of coördinaten verkeerd te initialiseren, wat zich uitte in visuele artefacten.


Verhaal

In een videohandler werd een structuur met geneste pointers gedeeltelijk geïnitialiseerd met = {0}, wat correct is voor globale variabelen, maar niet voor lokale. Hierdoor bevatten de pointers "rommel", wat leidde tot werken met ongeldige adressen en moeilijk te traceren crashes.


Verhaal

Bij het toevoegen van nieuwe velden aan een grote structuur hebben de auteurs de oude code-segmenten met op volgorde gebaseerde initialisatie niet bijgewerkt. Vanwege de niet-overeenkomende volgorde van velden en initialisatoren kregen kritische variabelen onjuiste waarden. Alleen een audit van de structuur en de implementatie van benoemde initialisatie hielpen de oorzaak te vinden.