les structures en C

25 Aug 2019 25 Aug 2019 34829 vues ESSADDOUKI Mostafa 8 min de lecture

Les structures en langage C

Une structure est un type de données défini par l'utilisateur qui permet de regrouper des éléments de types différents sous un même nom. Elle est l'outil fondamental pour modéliser des entités du monde réel (un point, une personne, un produit…) en associant leurs attributs dans un seul type cohérent.

Définition — Structure Une structure est un type composite défini avec le mot-clé struct. Elle regroupe un ensemble de membres (champs) pouvant être de types différents. Contrairement aux tableaux, les membres d'une structure n'ont pas besoin d'être du même type.

Schéma — structure regroupant des membres de types différents

ConceptTableauStructure
Types des élémentsTous identiquesDifférents
Accès aux élémentsPar indice tab[i]Par nom s.membre
Taille fixeOuiOui (somme des membres)
Cas d'usageCollection homogèneEntité hétérogène

1. Créer une structure


Syntaxe — Déclaration d'une structure C
struct NomStructure
{
    type1 membre1;
    type2 membre2;
    /* ... */
};   /* ne pas oublier le point-virgule final */

Exemple n°1 — Structure personne

struct personne
{
    char  nom[20];
    char  adresse[60];
    int   age;
    float salaire;
};
Remarque — Déclaration vs allocation Déclarer une structure avec struct crée uniquement un nouveau type — aucune mémoire n'est allouée. La mémoire est réservée uniquement lorsqu'une variable de ce type est créée.

2. Déclarer des variables de type structure

Il existe deux façons de déclarer une variable de type structure.

MéthodeDescriptionExemple
Avec la définitionVariable déclarée directement après }} p1;
SéparémentVariable déclarée plus tard comme un type de basestruct Point p1;

Exemple n°2 — Deux façons de déclarer une variable structure

/* Méthode 1 — variable déclarée avec la structure */
struct Point
{
    int x, y;
} p1;   /* p1 est déclarée immédiatement */


/* Méthode 2 — variable déclarée séparément */
struct Point
{
    int x, y;
};

int main(void)
{
    struct Point p1;   /* déclarée comme une variable ordinaire */
    return 0;
}
Astuce — typedef pour simplifier L'utilisation de typedef évite de répéter le mot-clé structà chaque déclaration de variable :
typedef struct
{
    int x, y;
} Point;

int main(void)
{
    Point p1;   /* plus besoin d'écrire "struct Point" */
    return 0;
}

3. Initialiser les membres

Les membres d'une structure ne peuvent pas être initialisés dans la déclaration du type. L'initialisation se fait lors de la création d'une variable, avec des accolades {} dans l'ordre de déclaration des membres.

Danger — Initialisation dans la déclaration du type Initialiser les membres directement dans le bloc structprovoque une erreur de compilation car aucune mémoire n'est encore allouée à ce stade :
/* Incorrect — erreur de compilation */
struct Point
{
    int x = 0;   /* erreur : ne peut pas initialiser ici */
    int y = 0;   /* erreur : ne peut pas initialiser ici */
};

Exemple n°3 — Initialisation valide avec {}

#include <stdio.h>

struct Point
{
    int x, y;
};

int main(void)
{
    /* x reçoit 0, y reçoit 1 — ordre de déclaration respecté */
    struct Point p1 = {0, 1};

    printf("x = %d, y = %d\n", p1.x, p1.y);

    return 0;
}
Sortie
x = 0, y = 1

4. Accéder aux membres

Les membres d'une structure sont accessibles via deux opérateurs selon le contexte :

OpérateurContexteSyntaxeExemple
. (point)Variable directevariable.membrep1.x
-> (flèche)Pointeur sur structurepointeur->membrep2->x

Exemple n°4 — Accès et modification via opérateur point

#include <stdio.h>

struct Point
{
    int x, y;
};

int main(void)
{
    struct Point p1 = {0, 1};

    p1.x = 10;   /* modification d'un membre */

    printf("x = %d, y = %d\n", p1.x, p1.y);

    return 0;
}
Sortie
x = 10, y = 1

5. Tableau de structures

Comme pour tout type de données, on peut créer un tableau de structures. Chaque case du tableau est une structure complète dont les membres sont accessibles via la notation tab[i].membre.


Syntaxe — Tableau de structures C
struct NomStructure tab[taille];

/* Accès aux membres */
tab[i].membre = valeur;

Exemple n°5 — Tableau de points et affichage

#include <stdio.h>

struct Point
{
    int x, y;
};

int main(void)
{
    struct Point tab[3];
    int i;

    /* Initialisation des 3 points */
    tab[0].x = 2;  tab[0].y = 3;
    tab[1].x = 5;  tab[1].y = 7;
    tab[2].x = 1;  tab[2].y = 4;

    /* Affichage */
    for (i = 0; i < 3; i++)
        printf("Point %d : x = %d, y = %d\n", i, tab[i].x, tab[i].y);

    return 0;
}
Sortie
Point 0 : x = 2, y = 3
Point 1 : x = 5, y = 7
Point 2 : x = 1, y = 4

6. Pointeur sur structure

On peut déclarer un pointeur sur une structure. Dans ce cas, les membres sont accessibles via l'opérateur -> (flèche), qui combine le déréférencement * et l'accès par point ..

Remarque — Équivalence -> et (*p).Les deux notations sont équivalentes :
p2->x        /* notation flèche — recommandée */
(*p2).x      /* déréférencement + point — équivalent */
La flèche est préférée car plus lisible.

Exemple n°6 — Pointeur sur structure

#include <stdio.h>

struct Point
{
    int x, y;
};

int main(void)
{
    struct Point  p1 = {0, 1};
    struct Point *p2 = &p1;   /* p2 pointe sur p1 */

    /* Accès via flèche */
    printf("via flèche  : x = %d, y = %d\n", p2->x,    p2->y);

    /* Accès via déréférencement + point — identique */
    printf("via (*p2).  : x = %d, y = %d\n", (*p2).x,  (*p2).y);

    /* Modification via le pointeur */
    p2->x = 99;
    printf("après p2->x=99 : p1.x = %d\n", p1.x);

    return 0;
}
Sortie
via flèche  : x = 0, y = 1
via (*p2).  : x = 0, y = 1
après p2->x=99 : p1.x = 99

Exemple n°7 — Passer une structure à une fonction via pointeur

#include <stdio.h>

struct Point
{
    int x, y;
};

/* Passage par pointeur — modifie la structure originale */
void translater(struct Point *p, int dx, int dy)
{
    p->x += dx;
    p->y += dy;
}

int main(void)
{
    struct Point p = {3, 4};

    printf("avant  : x = %d, y = %d\n", p.x, p.y);
    translater(&p, 10, -2);
    printf("après  : x = %d, y = %d\n", p.x, p.y);

    return 0;
}
Sortie
avant  : x = 3, y = 4
après  : x = 13, y = 2
Astuce — Toujours passer les structures par pointeur Passer une structure par valeur à une fonction entraîne la copie complète de tous ses membres — coûteux pour les grandes structures. Passer par pointeur (struct T *p) transmet uniquement une adresse (quelques octets), quelle que soit la taille de la structure.

7. Limitations des structures en C

Les structures C sont utiles mais présentent plusieurs limitations par rapport aux classes du C++ ou d'autres langages orientés objet.

LimitationDescriptionDisponible en C++ ?
Pas d'opérateursOn ne peut pas utiliser +, -… sur des variables structureOui (surcharge d'opérateurs)
Pas de masquageTous les membres sont accessibles depuis n'importe oùOui (private, protected)
Pas de fonctions membresOn ne peut pas définir de méthodes dans une structure COui (méthodes de classe)
Pas de membres statiquesImpossible de partager un membre entre toutes les instancesOui (static)
Pas de modificateurs d'accèspublic, private, protected absents en COui
Pas de constructeurInitialisation manuelle obligatoire à chaque créationOui (constructeurs)

Exemple n°8 — Limitation : opérateurs non applicables

struct number
{
    float x;
};

int main(void)
{
    struct number n1, n2, n3;
    n1.x = 4;
    n2.x = 3;

    n3 = n1 + n2;   /* erreur de compilation */

    return 0;
}
Sortie
error: invalid operands to binary + (have 'struct number' and 'struct number')
Contournement — Addition manuelle membre par membreEn C, il faut écrire explicitement l'opération sur chaque membre :
/* Contournement correct */
n3.x = n1.x + n2.x;

Récapitulatif

OpérationSyntaxeRemarque
Déclaration du typestruct Nom { ... };Ne réserve pas de mémoire
Déclaration de variablestruct Nom v;Réserve la mémoire
Initialisationstruct Nom v = {val1, val2};Ordre de déclaration respecté
Accès (variable)v.membreOpérateur point
Accès (pointeur)p->membreOpérateur flèche — préféré à (*p).membre
Tableau de structuresstruct Nom tab[n];Accès par tab[i].membre
Pointeur sur structurestruct Nom *p = &v;Passage efficace aux fonctions
typedeftypedef struct { ... } Nom;Évite de répéter struct

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.