Structures en langage C
From Wikipedia, the free encyclopedia
En langage C, le mot-clé `struct` permet de définir un type de données qui représente un enregistrement – un ensemble nommé de valeurs (appelées membres ou champs) qui occupe un bloc de mémoire. Il est possible d'accéder aux différentes valeurs via un seul identifiant, souvent par le biais d'un pointeur. Les structures pouvant contenir différents types de données, elles servent à créer des enregistrements de types mixtes. Par exemple, une structure représentant un client d'une banque peut contenir des champs pour son nom, son adresse, son numéro de téléphone et son solde.
Une structure occupe un bloc de mémoire contigu, dont la taille est généralement délimitée par la longueur des mots machine. Elle correspond à la fonctionnalité du même nom disponible dans certains assembleurs. Puisque le bloc de mémoire est contigu, chaque champ d'une structure se situe à un décalage fixe par rapport au début de celle-ci.
L'opérateur sizeof renvoie la taille totale (en octets) d'une structure donnée, comme pour les types de données primitifs. La façon dont les champs de la structure sont alignés (par rapport aux limites des mots machine) dépend de l'implémentation, et il peut y avoir de l'espacement (padding) entre deux champs consécutifs. Les compilateurs modernes prennent généralement en charge la directive #pragma pack, qui définit la taille en octets pour l'alignement[1].
Les structures du C sont inspirées de celles présente en ALGOL 68[2].
Déclaration
La déclaration de structure se fait à l'aide du mot-clé struct et de la liste, pour chaque champ, de son type et de son nom. La syntaxe est illustrée par cet exemple simple :
struct NomStructure {
Type membre1;
Type membre2;
};
Le nom de la structure peut être omis dans certains contextes.
Renommage (typedef)
Le mot-clé typedef permet de référencer un type structure sans avoir à écrire le mot-clé struct. Cependant, certains guides de style de programmation[3] déconseillent cette pratique, puisque le simple nom du type ne peut plus être distingué des noms de variables, fonctions, etc.
Par exemple :
typedef struct NomStructure {
Type membre1;
Type membre2;
} MaStructure;
struct NomStructure instance1;
// le type `struct NomStructure` peut être remplacé par `MaStructure`
MaStructure instance2;
En C++, l'utilisation de typedef est inutile car les types définis avec struct font déjà partie de l'espace de noms standard, et on peut donc y faire référence indifféremment par struct NomStructure ou MaStructure. De plus, C++ dispose aussi du mot-clé using qui permet de créer des alias pour les types utilisant des templates.
Initialisation
Il existe trois façons d'initialiser une structure en C.
Considérons le type simple suivant :
struct Point {
int x;
int y;
};
Les initialiseurs de type C89 peuvent être utilisés lorsque l'on peut fournir les valeurs des membres dans l'ordre[4]. Par exemple :
struct Point p = { 1, 2 };
Pour des listes d'éléments non contigus ou bien désordonnés, il est possible d'expliciter le nom de chaque champ[5] :
struct Point p = { .y = 2, .x = 1 };
Lorsqu'un initialiseur est fourni ou que l'objet est alloué statiquement, les éléments omis sont initialisés à 0. La troisième méthode d'initialisation d'une structure consiste à copier la valeur d'un objet pré-existant ayant le même type. Par exemple :
struct Point p2 = p1;
Copie
Il est possible de copier toutes les valeurs d'une structure dans une autre instance. Un compilateur peut utiliser la fonction standard memcpy() pour copier les octets du bloc mémoire.
struct Point a = { 1, 3 };
struct Point b;
b = a;
Pointeurs
Les pointeurs permettent d'accéder à une struct par son adresse. Cela permet notamment, lorsqu'une structure est passée en paramètre à une fonction, de n'avoir à copier que son adresse plutôt que la structure entière, ou encore de permettre la modification en place. L'opérateur -> est un raccourci (sucre syntaxique) qui déréférence le pointeur fourni à gauche et accède à la valeur d'un membre de la structure, dont le nom est passé à droite.
struct Point p = { 3, 7 };
// Accès direct :
int x = p.x;
p.x = 10;
struct Point* pp = &p;
// Accès via un pointeur :
x = pp->x;
pp->x = 8;
// La syntaxe ci-dessus est équivalente à :
x = (*pp).x;
(*pp).x = 8;
Dans les autres langages de programmation
Les langages de programmation D[6], Go, Julia[7], Rust, Swift et Zig[8] ont également des structures.
C++
En C++, les structures peuvent être déclarées avec struct et utilisées de la même manière qu'en C. Le C++ dispose aussi de classes qui sont identiques aux structures, à ceci près que les membres d'une classe ont une visibilité privée par défaut, tandis que les membres d'une structure sont publics par défaut.
.NET
Les langages .NET possèdent une fonctionnalité similaire aux structures en C, appelée struct en C# et Structure en Visual Basic .NET. Cette construction offre de nombreuses fonctionnalités d'une classe, mais se comporte comme un type valeur plutôt que comme un type référence : par exemple, lors du passage d'une structure .NET à une fonction, sa valeur est copiée afin que les éventuelles modifications faites au paramètre d'entrée n'affectent pas la valeur qui a été passée.