Les structures et unions en C peuvent être complexes à maîtriser en raison des diverses normes.
Une mauvaise compréhension peut entraîner un code inefficace et difficile à maintenir.
Cet article clarifie les concepts des structures et unions en C, en détaillant les normes C90, C99 et C11 avec des exemples pratiques.
Développez votre expertise en C et ouvrez la voie à des projets passionnants.
Structures et Unions : C90
Dans ce chapitre, nous explorerons en détail les concepts de structures et d’unions en C, avec un accent particulier sur les structures incomplètes et anonymes introduites par les normes C99 et C11. Nous commencerons par un rappel des structures en C90, puis nous aborderons les nouvelles fonctionnalités des normes ultérieures. Enfin, nous illustrerons les concepts avec des exemples de code et des démonstrations pratiques.
C99 : Structures Incomplètes
Définition et Déclaration des Structures
En C90, une structure est définie à l’aide du mot clé struct, suivi du nom du modèle de la structure, et des membres de la structure entre accolades. Voici un exemple de définition et de déclaration d’une structure :
#include
#include // Inclure pour utiliser strcpy
struct Person {
char name[50];
int age;
};
int main() {
struct Person p1; // Déclaration d'une variable de type struct Person
// Initialisation des membres de la structure
p1.age = 25;
strcpy(p1.name,
"Alice"); // Utilisation de strcpy pour copier la chaîne dans name
// Affichage des informations
printf("Name: %s\n", p1.name);
printf("Age: %d\n", p1.age);
return 0;
}
- Exemple d’exécution de code sur Eclipse
Syntaxe | Description |
---|---|
struct Person | Nom du modèle de la structure |
{ char name[50]; int age; } | Membres de la structure : un tableau de caractères et un entier |
struct Person p1; | Déclaration d’une variable de type struct Person |
Structures Sans Nom (Structures Anonymes)
En C90, il est possible de définir une structure sans spécifier un nom de modèle, ce qui peut être pratique pour les structures temporaires :
#include
int main() {
struct {
int x;
float y;
} temp;
temp.x = 10;
temp.y = 20.5;
printf("x: %d\n", temp.x);
printf("y: %.2f\n", temp.y);
return 0;
}
- Exemple d’exécution de code sur Eclipse
Syntaxe | Description |
---|---|
struct { int x; float y; } temp; | Définition d’une structure anonyme avec deux membres : un entier et un flottant |
temp.x et temp.y | Accès aux membres de la structure anonyme |
C11 : Structures Anonymes
Définition
Une structure incomplète est une déclaration de structure qui ne fournit pas les détails complets sur la disposition des membres de la structure. En C99, vous pouvez déclarer une structure sans spécifier ses membres, et utiliser des pointeurs vers cette structure.
Syntaxe
struct MyStruct; // Déclaration d'une structure incomplète
- Utilisation d’un pointeur vers une structure incomplète :
struct MyStruct *ptr; // Déclaration d'un pointeur vers une structure incomplète
Définition complète de la structure : struct MyStruct {
int member1;
char member2;
};
Utilisation
Les structures incomplètes sont souvent utilisées dans des contextes comme :
- Déclarations de pointeurs :Lorsqu’une fonction ou une structure a besoin d’utiliser des pointeurs vers une structure mais que la définition complète n’est pas encore disponible.
struct MyStruct; // Déclaration d'une structure incomplète
void function(struct MyStruct *ptr); // Utilisation d'un pointeur
- Déclarations de structures contenant des pointeurs :Lorsqu’une structure contient des pointeurs vers une autre structure qui est encore à définir.
struct Node {
struct Node *next; // Pointeur vers une structure incomplète
};
- Encapsulation de données :Pour créer des structures qui cachent les détails d’implémentation, permettant une abstraction et une encapsulation plus propres.
Exemple Complet
Voici un exemple complet illustrant l’utilisation des structures incomplètes :
#include
#include
struct Node; // Déclaration d'une structure incomplète
// Définition d'une structure utilisant un pointeur vers une structure
// incomplète
struct LinkedList {
struct Node *head;
};
// Définition complète de la structure Node
struct Node {
int data;
struct Node *next;
};
// Fonction pour créer un nouveau nœud
struct Node *create_node(int value) {
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
if (new_node == NULL) {
perror("Allocation failed");
exit(EXIT_FAILURE);
}
new_node->data = value;
new_node->next = NULL;
return new_node;
}
// Fonction pour afficher les éléments de la liste
void print_list(struct LinkedList *list) {
struct Node *current = list->head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
struct LinkedList list;
list.head = create_node(1);
list.head->next = create_node(2);
list.head->next->next = create_node(3);
print_list(&list);
// Libération de la mémoire
struct Node *current = list.head;
struct Node *next_node;
while (current != NULL) {
next_node = current->next;
free(current);
current = next_node;
}
return 0;
}
- Exemple d’exécution de code sur Eclipse
Allocation Dynamique avec Structures Incomplètes
Lors de l’utilisation de structures incomplètes, il est crucial d’ajuster la taille allouée dynamiquement pour inclure la taille du tableau. Cela se fait en ajoutant la taille du tableau à la taille de la structure lors de l’appel à malloc.
Élément | Taille (octets) |
---|---|
sizeof(struct Incomplete) | 4 (taille de int si la structure contient seulement un int) |
array_size * sizeof(int) | 40 (pour un tableau de 10 int) |
Total | 44 |
Comparaison : Structures en C
Introduction
Les structures anonymes ont été introduites avec le standard C11 pour offrir plus de flexibilité dans la définition de structures, en permettant leur utilisation sans nom. Cela simplifie la déclaration et l’initialisation des structures, surtout lorsqu’elles sont utilisées comme membres d’autres structures ou lorsqu’une structure est utilisée uniquement dans un contexte limité.
Utilisation des Structures Anonymes
Voici un exemple d’utilisation :
#include
int main() {
struct {
union {
struct {
int a;
float b;
};
char c[8];
};
} example;
example.a = 10;
example.b = 3.14f;
printf("a: %d\n", example.a);
printf("b: %.2f\n", example.b);
return 0;
}
- Exemple d’exécution de code sur Eclipse
Syntaxe | Description |
---|---|
struct { union { struct { int a; float b; }; char c[8]; }; } example; | Définition d’une structure avec une union anonyme contenant une structure et un tableau de caractères |
example.a et example.b | Accès aux membres de la structure anonyme imbriquée |
Avantages des Structures Anonymes :
- Simplicité :Elles permettent de déclarer des structures directement sans avoir à définir un type structuré nommé.
- Encapsulation :Elles sont souvent utilisées pour encapsuler des données dans des structures plus complexes, ce qui améliore la lisibilité du code.
- Flexibilité :Elles sont utiles pour les structures temporaires ou pour les structures utilisées uniquement dans un contexte limité.
Limitations :
- Réutilisation :Les structures anonymes ne peuvent pas être réutilisées ailleurs dans le code car elles n’ont pas de nom. Si une structure est nécessaire à plusieurs endroits, il est préférable de la définir avec un nom.
- Debugging :Les structures anonymes peuvent rendre le débogage un peu plus difficile, car les types ne sont pas nommés explicitement, ce qui peut compliquer l’analyse des fichiers de débogage.
Conclusion sur Structures et Unions
Les standards du langage C ont évolué au fil des années pour introduire de nouvelles fonctionnalités et améliorer la convivialité du langage. Voici un aperçu des principales différences entre les versions C90, C99 et C11 :
CaractéristiqueC90C99C11DéclarationsDéclarations en début de blocDéclarations mixtes autoriséesDéclarations mixtes autoriséesPrototypes de fonctionsNon obligatoireObligatoireObligatoireTypes de donnéesTypes primitifs de baseTypes étendus (long long, bool, etc.)Types étendus (incl. _Alignas, _Noreturn)Structures/UnionsMembres définis uniquementInitialisation flexiblePas de nouvelles caractéristiques spécifiquesBouclesBoucle for avec déclarations interditesBoucle for avec déclarations autoriséesBoucle for avec déclarations autoriséesPréprocesseurDirectives standardMacros variadiques, _PragmaPas de nouvelles caractéristiques spécifiquesGestion des threadsNon supportéNon supportéSupport via | Caractéristique | C90 | C99 | C11 |
---|---|---|---|---|
Déclarations | Déclarations en début de bloc | Déclarations mixtes autorisées | Déclarations mixtes autorisées | |
Prototypes de fonctions | Non obligatoire | Obligatoire | Obligatoire | |
Types de données | Types primitifs de base | Types étendus (long long, bool, etc.) | Types étendus (incl. _Alignas, _Noreturn) | |
Structures/Unions | Membres définis uniquement | Initialisation flexible | Pas de nouvelles caractéristiques spécifiques | |
Boucles | Boucle for avec déclarations interdites | Boucle for avec déclarations autorisées | Boucle for avec déclarations autorisées | |
Préprocesseur | Directives standard | Macros variadiques, _Pragma | Pas de nouvelles caractéristiques spécifiques | |
Gestion des threads | Non supporté | Non supporté | Support via | |
Atomicité | Non supporté | Non supporté | Support via | |
Unicode | Non supporté | Non supporté | Support amélioré (char16_t, char32_t) |
Caractéristique | C90 | C99 | C11 |
---|---|---|---|
Déclarations | Déclarations en début de bloc | Déclarations mixtes autorisées | Déclarations mixtes autorisées |
Prototypes de fonctions | Non obligatoire | Obligatoire | Obligatoire |
Types de données | Types primitifs de base | Types étendus (long long, bool, etc.) | Types étendus (incl. _Alignas, _Noreturn) |
Structures/Unions | Membres définis uniquement | Initialisation flexible | Pas de nouvelles caractéristiques spécifiques |
Boucles | Boucle for avec déclarations interdites | Boucle for avec déclarations autorisées | Boucle for avec déclarations autorisées |
Préprocesseur | Directives standard | Macros variadiques, _Pragma | Pas de nouvelles caractéristiques spécifiques |
Gestion des threads | Non supporté | Non supporté | Support via |
Atomicité | Non supporté | Non supporté | Support via |
Unicode | Non supporté | Non supporté | Support amélioré (char16_t, char32_t) |
Conclusion
Les structures et unions en C offrent une flexibilité importante pour la gestion des données. Avec les évolutions des normes C90, C99 et C11, de nouvelles fonctionnalités ont été introduites, telles que les structures incomplètes et anonymes. Ces fonctionnalités permettent d’écrire du code plus flexible et performant.
Formez-vous gratuitement avec Alphorm !
Maîtrisez les compétences clés en IT grâce à nos formations gratuites et accélérez votre carrière dès aujourd'hui.
FAQ
Qu'est-ce qu'une structure en C?
Comment utiliser les structures incomplètes en C99?
Quels sont les avantages des structures anonymes en C11?
Quels changements C99 a-t-il apporté aux structures en C?
Comment comparer C90, C99 et C11 pour les structures?
Conclusion
En conclusion, les structures et unions en C, avec leurs évolutions à travers les normes C90, C99 et C11, offrent une flexibilité considérable dans la gestion des données. Ces fonctionnalités améliorent la modularité et la performance du code. Quelle nouvelle fonctionnalité aimeriez-vous explorer davantage dans vos projets de programmation en C?