In de programmeertaal C kunnen structuren (struct) andere structuren en verschillende gegevens typen bevatten. De indeling van de velden binnen de structuur kan echter invloed hebben op de grootte en uitlijning. De compiler voegt extra bytes (padding) toe om de uitlijning (alignment) van het grootste veld te waarborgen. Dit is belangrijk voor de prestaties en correcte werking van de processor.
Als een structuur geneste structuren bevat, wordt de uitlijning recursief toegepast:
#pragma pack in MSVC of de attributen __attribute__((packed)) in GCC/Clang).Voorbeeld:
#include <stdio.h> struct Inner { char c; int x; }; struct Outer { char a; struct Inner b; short s; }; int main() { printf("sizeof(struct Inner) = %zu\n", sizeof(struct Inner)); printf("sizeof(struct Outer) = %zu\n", sizeof(struct Outer)); return 0; } // sizeof(struct Inner) = 8 (op 64-bit), sizeof(struct Outer) = 16 of 24
Het gebruik van pack en packed vermindert de grootte door de uitlijning te negeren, maar dit kan de prestaties verlagen of fouten veroorzaken op sommige platforms (ARM, DSP enz.).
Vraag: Kan je garanderen dat de grootte van dezelfde structuur op alle platforms hetzelfde is?
Antwoord: Nee! De C-standaard garandeert geen gelijke uitlijning, bytevolgorde (endian), en kan "padding" toevoegen tussen velden en aan het einde van de structuur. Voor binaire compatibiliteit van structuren gebruik handmatige uitlijningscontrole en test altijd expliciet sizeof op elk doelplatform.
Voorbeeld:
struct Data { char c; int x; }; // sizeof(Data) is meestal 8 op 64-bit, 5 of 8 op 32-bit
Geschiedenis
Bij het uitwisselen van een structuur tussen een microcontroller (ARM) en een pc via een binair protocol kwamen de van ARM ontvangen gegevens niet overeen met de verwachtingen op de pc — vanwege verschillende padding en byte-ordening. Hierdoor werden foutieve parameters gedecodeerd, wat leidde tot fysieke stuurfouten van het apparaat.
Geschiedenis
In een netwerkprotocol werden packed-structuren toegevoegd om de verzending van gegevens te versnellen, maar men had niet in de gaten dat op een platform zonder uitlijning afzonderlijke velden niet werkten (de processor ondersteunde geen misaligned toegang). Resultaat: hardware-excepties bij het werken met netwerkpakketten.
Geschiedenis
De server werkte met een extern bestand dat uit recordstructuren bestond. Na een compilerupdate veranderde de grootte van de structuur (een andere uitlijning). De oude gegevens in het bestand konden niet correct worden gelezen, en een deel van de informatie werd "beschadigd".