ProgrammationProgrammeur système

Expliquez la mécanique des structures imbriquées et de l'alignement des structures en C. Comment contrôler la taille d'une structure et quels problèmes peuvent survenir ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Dans le langage C, les structures (struct) peuvent inclure d'autres structures et différents types de données. Cependant, la disposition des champs à l'intérieur d'une structure peut influencer sa taille et son alignement. Le compilateur ajoute des octets supplémentaires (padding) pour respecter l'alignement (alignment) du champ le plus large. Cela est important pour les performances et le bon fonctionnement du processeur.

Si une structure contient des structures imbriquées, l'alignement est appliqué de manière récursive :

  • La taille de la structure est toujours multiple de l'alignement du champ le plus large.
  • Les structures imbriquées peuvent conduire à des retraits inattendus, rendant sizeof(struct) plus grand que la somme des sizeof(champs).

Comment contrôler la taille ?

  1. Trier les champs par ordre décroissant de taille.
  2. Utiliser des directives d'alignement (par exemple, #pragma pack dans MSVC ou l'attribut __attribute__((packed)) dans GCC/Clang).

Exemple :

#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 (sur 64 bits), sizeof(struct Outer) = 16 ou 24

L'utilisation de pack et packed réduit la taille en ignorant l'alignement, mais cela peut diminuer les performances ou provoquer des erreurs sur certaines plateformes (ARM, DSP, etc.).


Question piège.

Question : Peut-on garantir une taille identique d'une même structure sur toutes les plateformes ?

Réponse : Non ! La norme C ne garantit pas le même alignement, l'ordre des octets (endian), et peut "ajouter" du padding entre les champs et à la fin de la structure. Pour la compatibilité binaire des structures, utilisez une gestion manuelle de l'alignement et testez toujours explicitement sizeof sur chaque plateforme cible.

Exemple :

struct Data { char c; int x; }; // sizeof(Data) est généralement 8 sur 64 bits, 5 ou 8 sur 32 bits

Histoire

Lors de l'échange d'une structure entre un microcontrôleur (ARM) et un PC via un protocole binaire, les données provenant de l'ARM ne correspondaient pas aux attentes sur le PC — en raison de différents padding et ordres d'octets. Cela a conduit à des paramètres mal décodés, entraînant des erreurs physiques dans le contrôle de l'appareil.


Histoire

Dans un protocole réseau pour accélérer l'envoi de données, des structures packed ont été ajoutées, mais il n'a pas été pris en compte que sur une plateforme sans alignement, certains champs ne fonctionnaient pas (le processeur ne supportait pas l'accès non aligné). Résultat : exceptions matérielles lors du travail avec des paquets réseau.


Histoire

Le serveur travaillait avec un fichier externe composé d'enregistrements de structure. Après la mise à jour du compilateur, la taille de la structure a changé (autre alignement). Les anciennes données dans le fichier ont cessé d'être lues correctement, une partie des informations est devenue "corrompue".