Concepts avancés du langage C


précédentsommairesuivant

V. Structures, unions et énumérations

V-A. Les structures

Une structure est une variable qui regroupe une ou plusieurs variables, non nécessairement de même type (contrairement aux tableaux), appelées champs. L'accès à un champ d'une structure se fait par l'intermédiaire de l'opérateur point. Par exemple :

 
Sélectionnez
struct {char nom[20]; int age;} marc, luc, jean;
...
strcpy(marc.nom, "Marc");
marc.age = 24 ;
...

D'habitude on renomme tout d'abord une structure avant de l'utiliser. Par exemple :

 
Sélectionnez
typedef struct {char nom[20]; int age;} PERSONNE;
...
PERSONNE marc, luc, jean;
...

Une structure peut être également nommée. Par exemple :

 
Sélectionnez
struct personne_s {char nom[20]; int age;} marc, luc, jean;

Dans ce cas, marc, luc et jean sont de type struct personne_s. On aurait également pu écrire :

 
Sélectionnez
struct personne_s {
    char nom[20];
    int age;
};

Puis :

 
Sélectionnez
struct personne_s marc, luc, jean;

Et bien entendu, du moment qu'une structure a été nommée, on peut très bien écrire :

 
Sélectionnez
typedef struct personne_s PERSONNE;

L'opérateur = (affectation) peut être utilisé avec des structures (pour copier une structure) mais dans la pratique on n'en a rarement besoin. En effet, puisque l'espace occupée en mémoire par une structure peut être gigantesque, copier une structure vers une autre pénalisera considérablement, non seulement en termes de performances mais aussi en termes de vitesse d'exécution (à cause du temps d'accès à une cellule mémoire). C'est pourquoi on utilise généralement des pointeurs pour manipuler les structures. L'opérateur -> permet d'accéder à un champ d'une structure via un pointeur. Par exemple :

 
Sélectionnez
#include <stdio.h>
#include <string.h>

struct personne_s {
    char nom[20];
    int age;
};

void affiche_personne(struct personne_s * p);

int main()
{
    struct personne_s jean;

    strcpy(jean.nom, "Jean");
    jean.age = 24;

    affiche_personne(&jean);

    return 0;
}

void affiche_personne(struct personne_s * p)
{
    printf("Nom : %s\n", p->nom);
    printf("Age : %d\n", p->age);
}

L'initialisation d'une structure se fait de la même manière que pour un tableau, avec les mêmes règles. Par exemple :

 
Sélectionnez
struct personne_s jean = {"Jean", 24};

V-B. Les unions

Une union est, en première approximation, une variable dont le type n'est pas figé (c'est-àdire une variable « caméléon »). En fait, une variable de type union est une variable composée de champs de types différents et non nécessairement de même taille, mais à la différence d'une structure, les champs d'une union partagent le même emplacement mémoire. Les unions permettent donc de faire une économie de mémoire. Du point de vue syntaxique, elles ressemblent beaucoup aux structures, il suffit de remplacer struct par union.

Le programme suivant montre un exemple d'utilisation de cette union, u, entre trois variables de types différents (n, x et p).

 
Sélectionnez
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

union trois_en_un {
    int n;
    double x;
    char * p;
};

int main()
{
    union trois_en_un u;
    
    printf("Entrez un entier : ");
    scanf("%d", &(u.n));
    printf("Vous avez entre : %d\n\n", u.n);
    
    printf("Entrez un nombre flottant : ");
    scanf("%lf", &(u.x));
    printf("Vous avez entre : %f\n\n", u.x);
    
    u.p = malloc(20);
    if (u.p != NULL)
    {
        strcpy(u.p, "Au revoir.");
        printf("%s\n\n", u.p);
        free(u.p);
    }
    
    return 0;
}

Puisque les champs d'une union utilisent le même espace mémoire, les unions sont également utilisées pour interpréter un même motif binaire dans différents contextes (par exemple pour interpréter le contenu d'une mémoire comme un flottant, ou comme un entier, ...), mais cette pratique est généralement utilisée dans les programmes de très bas niveau plutôt que dans des programmes portables.

V-C. Les champs de bits

Le langage C permet de créer, à l'intérieur d'une structure, des données (champs) dont la taille est spécifiée en bits. Ces champs doivent être de type entier. Par exemple :

 
Sélectionnez
struct {
    unsigned a : 1;
    unsigned b : 1;
    unsigned c : 4;
    unsigned d : 3;
} x;

Ici, on a une structure x composée de 4 champs tous de type unsigned int : a de taille = 1 bit, b de taille = 1 bit, c de taille = 4 bits, et d de taille = 3 bits. Cela ne signifie pas que la taille de x est de 9 bits mais au moins 9 bits. La taille d'une donnée est toujours un multiple entier d'un "octet".

Les champs de bits peuvent être également utilisés, en faisant une union avec un autre type, dans des programmes dépendantes d'une plateforme particulière pour accéder directement aux bits d'une donnée quelconque. On retrouve alors l'intérêt de créer des champs sans noms : ils sont juste utilisés pour espacer des champs entre eux. Dans des programmes portables, on utilisera plutôt les opérateurs de manipulation de bits que les unions et les champs de bits.

Attention ! Puisque les champs d'un champ de bits représentent des bits d'une variable et non des variables indépendantes, on ne peut pas leur appliquer l'opérateur & (adresse de). Mais il peut bien entendu être appliqué à la structure elle-même qui est une variable comme toutes les autres.

V-D. Les énumérations

Une énumération est un sous-ensemble énuméré du type int. La déclaration d'une énumération ressemble un peu à celle d'une structure Par exemple :

 
Sélectionnez
typedef enum {
    PION,
    CAVALIER,
    FOU,
    TOUR,
    REINE,
    ROI
} CLASSE;
...
CLASSE classe = FOU; /* Ou egalement int classe = FOU; */
...

Qu'on aurait également pu écrire :

 
Sélectionnez
#define PION 0
#define CAVALIER PION + 1
#define FOU CAVALIER + 1
#define TOUR FOU + 1
#define REINE TOUR + 1
#define ROI REINE + 1
...
int classe = FOU;
...

L'opérateur = peut également être utilisé dans une déclaration d'un type énuméré pour assigner explicitement une valeur à une constante.


précédentsommairesuivant

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Melem. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.