Programmation C
struct, typedef et enum
Cours Exercices Correction des exercices

struct typedef enum

struct

  • Possibilité d'agréger les informations au sein de variables conteneurs
  • Intérêt
    • Modélisation de l'information stockée dans les applications informatiques mimant la façon avec laquelle elle existe concrètement : de façon structurée
    • Manipulation de plusieurs informations en une seule information
    • Amélioration de l'expréssivité du code
      • Utilisation de noms de types expressifs
      • Explicitation du lien existant entre certaines variables par référence à la variable qui les "contient"
    • Simplification du code
    • ...
  • Définition : struct
  • Type informatique construit par agrégation d'un ensemble de champs utilisé pour déclarer des variables agrégeant des sous-variables
  • Syntaxe
    struct nomStruct {
      nomType1 nomChamp1;
      nomType2 nomChamp2;
      ...
      nomTypeN nomChampN;
    };
    Déclaration d'un type struct nommé nomStruct comportant N champs nommés nomChamp1, nomChamp2, ..., nomChampN de types respectifs nomType1, nomType2, ..., nomTypeN
  • Attention, déclaration de tout type struct avant son utilisation dans l'ordre de compilation du code
    • Déclaration des struct habituellement réalisée en début de fichier avant les fonctions qui vont les utiliser
    • Possibilité peu utilisée : déclaration locale à une fonction
  • Déclaration d'une variable selon un type struct
    struct nomStruct nomVariable;
    Valeurs des champs aléatoires
    struct nomStruct nomVariable = { v1,v2,...,vN };
    Valeurs des champs initialisées avec les valeurs données entre accolades (dans l'ordre et sous réserve que les types correspondent)
  • Déclaration d'une variable pointeur sur un type struct
    struct nomStruct* nomVariable;
  • Déclaration d'une variable pointeur sur pointeur sur un type struct
    struct nomStruct** nomVariable;
  • Accès aux champs d'une variable nomVariable de type struct
    nomVariable.nomChamp
  • Accès aux champs d'une variable nomVariable de type pointeur sur struct
    (*nomVariable).nomChamp
    ou plus lisiblement
    nomVariable->nomChamp
  • Opérateurs
    • = : affectation champ pour champ
    • sizeof : nombre d'octets d'une variable déclarée selon un type struct
    • & : adresse d'une variable déclarée selon un type struct
    • * : valeur d'une variable déclarée de type pointeur sur type struct
  • Exemples
  • #include <stdio.h>

    struct date {
      int jour;
      int mois;
      int annee;
    };

    void main(void) {
      struct date d;
      d.jour = 2;
      d.mois = 8;
      d.annee = 1993;
      printf("%02d:%02d:%d\n", d.jour, d.mois, d.annee);
    }

    Struct1.c - Struct1.exe
    • Définition d'une struct date composée de trois champs de type entier
      • jour
      • mois
      • année
    • Un programme principal qui définit une variable de type struct date, qui initialise individuellement et successivement ses champs, et qui les affiche.
    02:08:1993

    #include <stdio.h>

    struct date {
      int jour;
      int mois;
      int annee;
    };

    void main(void) {
      struct date d1;
      struct date d2 = {  2, 8,1993 };
      struct date d3 = { 11,10,2001 };
      struct date d4 = {  0, 0,   0 };
      struct date* d;
      d1.jour = 2;
      d1.mois = 8;
      d1.annee = 1993;
      printf("d1 : %02d:%02d:%4d %p\n", d1.jour, d1.mois, d1.annee,&d1);
      printf("d2 : %02d:%02d:%4d %p\n", d2.jour, d2.mois, d3.annee,&d2);
      printf("d3 : %02d:%02d:%4d %p\n", d3.jour, d3.mois, d3.annee,&d3);
      printf("\n");
      printf("d4 : %02d:%02d:%4d %p\n", d4.jour, d4.mois, d4.annee,&d4);
      d4 = d1;
      printf("d4 : %02d:%02d:%4d %p\n", d4.jour, d4.mois, d4.annee,&d4);
      printf("\n");
      printf("%zu\n", sizeof(struct date));
      printf("%p\n", &d1);
      printf("%p\n", &d1.jour);
      printf("%p\n", &d1.mois);
      printf("%p\n", &d1.annee);
      printf("\n");
      d = &d3;
      printf("*d : %02d:%02d:%4d %p\n", (*d).jour, (*d).mois, (*d).annee, d);
      printf("*d : %02d:%02d:%4d %p\n", d->jour, d->mois, d->annee, d);
    }

    Struct2.c - Struct2.exe
    • Reprise du programme Struct1.c et démonstration de quelques possibilités supplémentaires
      • Initialisation des champs d'une variable struct au moment de sa définition en utilisant une liste de valeurs données entre accolade
      • Définition d'une variable de type pointeur sur struct
      • Affectation entre variables de mêmes types struct en utilisant le signe =
      • Calcul du nombre d'octets occupés par une variable de type struct
      • Affichage de l'adresse d'une variable de type struct et des adresses de ses champs
      • Affectation d'une variable de type pointeur sur struct avec l'adresse d'une variable de type struct
      • Affichage des valeurs des champs appartenant à une variable pointée par un pointeur sur struct
    d1 : 02:08:1993 000000045E0FF9F0
    d2 : 02:08:2001 000000045E0FFA10
    d3 : 11:10:2001 000000045E0FF9E0

    d4 : 00:00:   0 000000045E0FFA00
    d4 : 02:08:1993 000000045E0FFA00

    12
    000000045E0FF9F0
    000000045E0FF9F0
    000000045E0FF9F4
    000000045E0FF9F8

    *d : 11:10:2001 000000045E0FF9E0
    *d : 11:10:2001 000000045E0FF9E0
  • Fonctions et struct
    • Compatibilité des types struct avec la programmation de fonctions
    • Utilisation comme n'importe quel type primitif
    • Exemples
    • #include <stdio.h>
      #include <stdbool.h>

      struct horaire {
        int heure;
        int minute;
        int seconde;
      };

      void afficherHoraire(struct horaire h) {
        printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
      }

      int calculerSecondes(struct horaire h) {
        return h.heure * 3600 + h.minute * 60 + h.seconde;
      }

      int comparerHoraires(struct horaire h1, struct horaire h2) {
        int m1 = calculerSecondes(h1);
        int m2 = calculerSecondes(h2);
        if (m1 > m2) {
          return 1;
        }
        if (m1 < m2) {
          return -1;
        }
        return 0;
      }

      void ajouterUneSeconde(struct horaire* h) {
        h->seconde++;
        if (h->seconde == 60) {
          h->seconde = 0;
          h->minute++;
          if (h->minute == 60) {
            h->minute = 0;
            h->heure++;
            if (h->heure == 24) {
              h->heure = 0;
            }
          }
        }
      }

      void main(void) {
        struct horaire h1 = { 12, 59,59 };
        struct horaire h2 = { 23, 59,59 };
        afficherHoraire(h1);
        printf(" = %d secondes\n", calculerSecondes(h1));
        afficherHoraire(h2);
        printf(" = %d secondes\n", calculerSecondes(h2));
        printf("\n");
        printf("%d\n", comparerHoraires(h1, h1));
        printf("%d\n", comparerHoraires(h1, h2));
        printf("%d\n", comparerHoraires(h2, h1));
        printf("\n");
        ajouterUneSeconde(&h1);
        afficherHoraire(h1);
        printf("\n");
        ajouterUneSeconde(&h2);
        afficherHoraire(h2);
        printf("\n");
      }

      StructsEtFonctions1.c - StructsEtFonctions1.exe
      • Définition d'une struct horaire
      • Quatre fonctions avec passage de paramètres de type struct
        • Une fonction void avec un paramètre de type struct horaire
        • Une fonction à retour int avec un paramètre de type struct horaire
        • Une fonction à retour int avec deux paramètres de type struct horaire
        • Une fonction void avec un paramètre de type pointeur sur struct horaire
          • Utilisation de ce passage par adresse pour rendre possible la modification de la struct horaire passée en paramètre
      • Un programme principal de réalisation de différents tests
      12:59:59 = 46799 secondes
      23:59:59 = 86399 secondes

      0
      -1
      1

      13:00:00
      00:00:00

      #include <stdio.h>

      struct horaire {
        int heure;
        int minute;
        int seconde;
      };

      void afficherHoraire(struct horaire h) {
        printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
      }

      int calculerSecondes(struct horaire h) {
        return h.heure * 3600 + h.minute * 60 + h.seconde;
      }

      struct horaire calculerHoraire(int secondes) {
        struct horaire h = { secondes / 3600,(secondes / 60) % 60,secondes % 60 };
        return h;
      }

      struct horaire calculerHoraireSecondeSuivante(struct horaire h) {
        struct horaire nh = h;
        nh.seconde++;
        if (nh.seconde == 60) {
          nh.seconde = 0;
          nh.minute++;
          if (nh.minute == 60) {
            nh.minute = 0;
            nh.heure++;
            if (nh.heure == 24) {
              nh.heure = 0;
            }
          }
        }
        return nh;
      }

      void main(void) {
        int s = 53227;
        struct horaire h = calculerHoraire(s);
        printf("%d secondes = ", s);
        afficherHoraire(h);
        printf("\n");
        struct horaire h2 = calculerHoraireSecondeSuivante(h);
        afficherHoraire(h2);
        printf("\n");
        h2 = calculerHoraireSecondeSuivante(h2);
        afficherHoraire(h2);
        printf("\n");
      }

      StructsEtFonctions2.c - StructsEtFonctions2.exe
      • Définition d'une struct horaire
      • Deux fonctions avec passage de paramètres de type struct
        • Une fonction void avec un paramètre de type struct horaire
        • Une fonction à retour int avec un paramètre de type struct horaire
      • Deux fonctions avec retour de type struct
      • Un programme principal de réalisation de différents tests
      53227 secondes = 14:47:07
      14:47:08
      14:47:09
  • Tableaux de type élémentaire de type struct
    • Pas de problème particulier en allocation statique comme en allocation dynamique
    • Exemple
    • #include <stdio.h>
      #include <stdlib.h>

      struct horaire {
        int heure;
        int minute;
        int seconde;
      };

      void afficherHoraire(struct horaire h) {
        printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
      }

      void afficherTableauHoraires(struct horaire* th, int taille) {
        for (int i = 0; i < taille; i++) {
          afficherHoraire(th[i]);
          printf("\n");
        }
      }

      void afficherTableauPointeursHoraire(struct horaire** th, int taille) {
        for (int i = 0; i < taille; i++) {
          afficherHoraire(*th[i]);
          printf("\n");
        }
      }

      struct horaire tirerAuSortHoraire(void) {
        struct horaire h = { rand() % 24,rand() % 60,rand() % 60 };
        return h;
      }

      struct horaire* creerTableauHorairesTiresAuSort(int taille) {
        struct horaire* th = (struct horaire*) calloc(taille, sizeof(struct horaire));
        if (th != NULL) {
          for (int i = 0; i < taille; i++) {
            th[i] = tirerAuSortHoraire();
          }
        }
        return th;
      }

      struct horaire** creerTableauHoraires(int taille) {
        struct horaire** th = (struct horaire**) calloc(taille, sizeof(struct horaire*));
        if (th != NULL) {
          int i = 0;
          while ((i < taille) && 
                 ((th[i] = (struct horaire*) calloc(1, sizeof(struct horaire))) != NULL)) {
            i++;
          }
          if (th[taille - 1] == NULL) {
            for (int j = 0; j < i; j++) {
              free(th[j]);
              th[j] = NULL;
            }
          }
        }
        return th;
      }

      void libererTableauHoraires(struct horaire** th, int taille) {
        if (th != NULL) {
          for (int i = 0; i < taille; i++) {
            free(th[i]);
            th[i] = NULL;
          }
          free(th);
          th = NULL;
        }
      }

      #define TAILLE_1 5

      void tester1(void) {
        const int seed = 6;
        srand(seed);
        struct horaire th[TAILLE_1];
        printf("%d %zu %zu\n", TAILLE_1, sizeof(struct horaire), sizeof(th));
        for (int i = 0; i < TAILLE_1; i++) {
          th[i] = tirerAuSortHoraire();
        }
        afficherTableauHoraires(th, TAILLE_1);
        printf("\n");
      }

      #undef TAILLE_1

      void tester2(int taille) {
        const int seed = 6;
        srand(seed);
        struct horaire* th = (struct horaire*) calloc(taille, sizeof(struct horaire));
        printf("%d %zu %zu\n",taille, sizeof(struct horaire*), sizeof(th));
        if (th != NULL) {
          afficherTableauHoraires(th, taille);
          printf("\n");
          for (int i = 0; i < taille; i++) {
            th[i] = tirerAuSortHoraire();
          }
          afficherTableauHoraires(th, taille);
          free(th);
          th = NULL;
        }
        printf("\n");
      }

      void tester3(int taille) {
        const int seed = 6;
        srand(seed);
        struct horaire* th = creerTableauHorairesTiresAuSort(taille);
        printf("%d %zu %zu\n", taille, sizeof(struct horaire*), sizeof(th));
        if (th != NULL) {
          afficherTableauHoraires(th, taille);
          free(th);
          th = NULL;
        }
        printf("\n");
      }

      void tester4(int taille) {
        const int seed = 6;
        srand(seed);
        struct horaire** th = creerTableauHoraires(taille);
        printf("%d %zu %zu\n", taille, sizeof(struct horaire**), sizeof(th));
        if (th != NULL) {
          afficherTableauPointeursHoraire(th, taille);
          libererTableauHoraires(th, taille);
          th = NULL;
        }
        printf("\n");
      }

      void main(void) {
        tester1();
        tester2(3);
        tester3(4);
        tester4(5);
      }

      TableauxDeStruct.c - TableauxDeStruct.exe
      • Définition d'une struct horaire
      • Diverses fonctions illustrant l'utilisation
        • de tableaux de struct horaire
          • en allocation statique
          • en allocation dynamique
        • de tableaux de pointeurs sur struct horaire en allocation dynamique
      • Un programme principal de réalisation de différents tests
      5 12 60
      10:13:59
      01:46:09
      16:22:56
      20:46:45
      00:55:58

      3 8 8
      00:00:00
      00:00:00
      00:00:00

      10:13:59
      01:46:09
      16:22:56

      4 8 8
      10:13:59
      01:46:09
      16:22:56
      20:46:45

      5 8 8
      00:00:00
      00:00:00
      00:00:00
      00:00:00
      00:00:00
  • Type struct avec champ(s) de type tableau
    • Pas de problème particulier en allocation statique comme en allocation dynamique pour les champs
    • Exemple
    • #include <stdio.h>
      #include <stdlib.h>

      struct clefStatique {
        char encode[128];
        char decode[128];
      };

      struct clefDynamique {
        char* encode;
        char* decode;
      };

      void initialiserTableauEncodage(char* encode, int delta) {
        for (int i = 0; i < 128; i++) {
          encode[i] = (i + delta + 128) % 128;
        }
      }

      void initialiserTableauDecodage(char* decode, char* encode) {
        for (int i = 0; i < 128; i++) {
          decode[encode[i]] = (char) i;
        }
      }

      struct clefStatique creerClefStatique(int delta) {
        struct clefStatique cs;
        initialiserTableauEncodage(cs.encode, delta);
        initialiserTableauDecodage(cs.decode, cs.encode);
        return cs;
      }

      struct clefDynamique creerClefDynamique(int delta) {
        struct clefDynamique cd;
        cd.encode = (char*) calloc(128, sizeof(char));
        if (cd.encode != NULL) {
          initialiserTableauEncodage(cd.encode, delta);
        }
        cd.decode = (char*) calloc(128, sizeof(char));
        if (cd.decode != NULL) {
          initialiserTableauDecodage(cd.decode, cd.encode);
        }
        return cd;
      }

      void libererClefDynamique(struct clefDynamique cd) {
        if (cd.encode != NULL) {
          free(cd.encode);
          cd.encode = NULL;
        }
        if (cd.decode != NULL) {
          free(cd.decode);
          cd.decode = NULL;
        }
      }

      void main(void) {
        printf("Taille d'une clef statique  : %zu octets\n", sizeof(struct clefStatique));
        printf("Taille d'une clef dynamique : %zu octets\n", sizeof(struct clefDynamique));
        printf("\n");
        struct clefStatique cs = creerClefStatique(4);
        struct clefDynamique cd = creerClefDynamique(-6);
        printf("Taille de la clef cs        : %zu octets\n", sizeof(cs));
        printf("Taille de la clef cd        : %zu octets\n", sizeof(cd));
        printf("\n");
        char c1 = 'A';
        char ec1 = cs.encode[c1];
        char dec1 = cs.decode[ec1];
        printf("%c %c %c\n", c1, ec1, dec1);
        char c2 = 's';
        char ec2 = cd.encode[c2];
        char dec2 = cd.decode[ec2];
        printf("%c %c %c\n", c2, ec2, dec2);
        libererClefDynamique(cd);
        printf("\n");
      }

      StructsDeTableaux.c - StructsDeTableaux.exe
      • Définition de deux struct "clef de chiffrage" fonctionnant de la même façon
        • la première clef avec champs de type tableau statique
        • la seconde clef avec champs de type tableau dynamique
      • Un champ pour le tableau permettant le chiffrage (caractère chiffré = t[caractère à chiffrer])
      • Un champ pour le tableau permettant le déchiffrage (caractère déchiffré = t[caractère à déchiffrer])
      • Exemples de fonctions
        • de création de clefs (chiffrage par décalage du code ASCII vers la droite ou vers la gauche)
        • d'utilisation d'une clef pour calculer le caractère chiffré par une clef à partir d'un caractère particulier
        • d'utilisation d'une clef pour calculer le caractère déchiffré par une clef à partir d'un caractère particulier chiffré
      • Un programme principal de réalisation de différents tests
      Taille d'une clef statique  : 256 octets
      Taille d'une clef dynamique : 16 octets
      Taille de la variable cs    : 256 octets
      Taille de la variable cd    : 16 octets
  • Type struct avec champ de type struct
    • Possible dans la mesure où aucun cycle de struct non pointeur n'est créé (type struct A possèdant un champ de type struct A directement ou indirectement)
    • Exemple
    • #include <stdio.h>
      #include <math.h>

      struct position {
        double x;
        double y;
      };

      struct segment {
        struct position pi;
        struct position pf;
      };

      struct triplet {
        struct segment s1;
        struct segment s2;
        struct segment s3;
      };

      double calculerLongueurSegment(struct segment s) {
        return sqrt(pow(s.pi.x - s.pf.x, 2.0) + pow(s.pi.y - s.pf.y, 2.0));
      }

      double calculerLongueurMaxSegments(struct triplet trp) {
        double l1 = calculerLongueurSegment(trp.s1);
        double l2 = calculerLongueurSegment(trp.s2);
        double l3 = calculerLongueurSegment(trp.s3);
        if ((l1 >= l2) && (l1 >= l3)) {
          return l1;
        }
        if (l2 >= l3) {
          return l2;
        }
        return l3;
      }

      void main(void) {
        printf("%zu %zu %zu\n", sizeof(struct triplet),
          sizeof(struct segment),
          sizeof(struct position));
        struct triplet trp = { { {  1.2, 3.4 },{ -2.3, 4.6 } },
                               { {  4.5,-5.6 },{  7.2, 1.4 } },
                               { { -5.3, 0.0 },{ -1.3, 8.9 } } };
        printf("%zu %zu %zu\n", sizeof(trp), sizeof(trp.s2), sizeof(trp.s2.pi));
        printf("\n");
        printf("Longueur maximale des segments : %lf\n", calculerLongueurMaxSegments(trp));
      }

      StructsDeStructs.c - StructsDeStructs.exe
      • Définition de trois struct imbriquées
        • struct position
        • struct segment qui possède des champs de type struct position
        • struct triplet qui possède des champs de type struct segment
      • Deux fonctions
        • Calcul de la longueur d'une struct segment
        • Calcul de la longueur du segment de longueur maximale des segments d'une struct segment
      • Un programme principal de réalisation de différents tests
        • Affichage des nombres d'octets nécessaires au stockage d'une struct position, d'une struct segment et d'une struct triplet
        • Définition et initialisation d'une variable de type struct triplet
        • Affichage des nombres d'octets nécessaires au stockage
          • de cette variable
          • d'un des champs de type struct segment de cette variable
          • d'un des champs de type position d'un des champs de type segment de cette struct triplet
        • Calcul et affichage de la longueur maximale des segments de cette struct triplet
      96 32 16
      96 32 16

      Longueur maximale des segments : 9.757561
  • Type struct avec champ de type pointeur sur type struct
    • Pas de problème particulier même avec cycle
    • Exemple
    • #include <stdlib.h>
      #include <stdio.h>
      #include <math.h>

      struct sommet {
        double x;
        double y;
      };

      struct polygone {
        int ns;
        struct sommet* ts;
      };

      void afficherSommet(struct sommet s) {
        printf("%6.2lf%6.2lf", s.x, s.y);
      }

      double calculerDistanceSommets(struct sommet s1, struct sommet s2) {
        return sqrt(pow(s1.x - s2.x, 2.0) + pow(s1.y - s2.y, 2.0));
      }

      struct sommet creerSommet() {
        struct sommet s;
        s.x = (rand() % 101) / 100.0;
        s.y = (rand() % 101) / 100.0;
        return s;
      }

      double calculerPerimetrePolygone(struct polygone p) {
        double l = 0.0;
        for (int i = 0; i < p.ns - 1; i++) {
          l += calculerDistanceSommets(p.ts[i], p.ts[i + 1]);
        }
        l+= calculerDistanceSommets(p.ts[p.ns - 1], p.ts[0]);
        return l;
      }

      void afficherPolygone(struct polygone p) {
        printf("%d sommets\n", p.ns);
        for (int i = 0; i < p.ns; i++) {
          afficherSommet(p.ts[i]);
          printf("\n");
        }
      }

      struct polygone creerPolygone(int n) {
        struct polygone p;
        p.ts = (struct sommet*) calloc(n, sizeof(struct sommet));
        if (p.ts == NULL) {
          p.ns = 0;
        }
        else {
          p.ns = n;
          for (int i = 0; i < n; i++) {
            p.ts[i] = creerSommet();
          }
        }
        return p;
      }

      void detruirePolygone(struct polygone pl) {
        if (pl.ts != NULL) {
          free(pl.ts);
          pl.ts = NULL;
        }
      }

      void main(void) {
        srand(2);
        printf("%zu %zu\n", sizeof(struct polygone), sizeof(struct sommet));
        struct polygone pl = creerPolygone(5);
        printf("%zu\n", sizeof(pl));
        printf("\n");
        afficherPolygone(pl);
        printf("Perimetre : %lf\n", calculerPerimetrePolygone(pl));
        detruirePolygone(pl);
      }

      StructsDePointeursSurStructs.c - StructsDePointeursSurStructs.exe
      • Définition de deux struct
        • Une struct sommet à valeurs réelles en deux dimensions
        • Une struct polygone permettant de stocker un polygone formé de sommets et définie au moyen de deux champs
          • Un entier ns pour le nombre de sommets
          • Un tableau de sommets alloué dynamiquement
      • Quelques fonctions utilisant la struct polygone
        • Création d'un polygone
        • Destruction d'un polygone
        • Affichage texte du nombre de sommets et des sommets d'un polygone
        • Calcul du périmètre d'un polygone
      • Un programme principal de réalisation de différents tests
      16 16
      16

      5 sommets
      0.45 0.27
      0.59 0.19
      0.93 0.56
      0.46 0.70
      1.00 0.35
      Perimetre : 2.353441

typedef

  • Possibilité de donner un nom de type alternatif à tout autre type (primitif ou non)
  • Intérêts
    • Qualification des informations par les noms des variables et des constantes qui les contiennent mais aussi par les noms des types de ces variables et de ces constantes
      -> Amélioration de l'expressivité du code
    • Simplification de l'écriture par la disparition du mot réservé struct quand le typedef porte sur un struct
    • Simplification de l'écriture par la disparition du mot réservé enum quand le typedef porte sur un enum (voir ci-dessous)
    • ...
  • Inconvénients
    • Disparition de l'indication explicite de la nature véritable des choses
      • Type pointeur pas visible en tant que type pointeur alors que s'en est bien un et qu'il est utilisé en tant que tel
        Suggestion : ajout de la lettre p en première lettre du type typedef
      • Type struct pas visible en tant que type struct
    • ...
  • Exemples
  • #include <stdio.h>

    typedef double altitude;
    typedef charpchar;

    void main(void) {
      altitude v = 3.342;
      printf("%lf\n", v);
      char c = 'z';
      pchar ptr = &c;
      printf("%p %c\n",ptr, *ptr);
    }

    Typedef1.c - Typedef1.exe
    • Déclaration via enum d'un type "altitude" équivalent au type double
    • Déclaration via enum d'un type "pchar" équivalent au type pointeur sur char
    • Utilisation de ces types dans un programme
    3.342000
    000000ED49B1FB10 z

    #include <stdio.h>

    typedef struct {
      int heure;
      int minute;
      int seconde;
    horaire;

    void afficherHoraire(horaire h) {
      printf("%02d:%02d:%02d",h.heure,h.minute,h.seconde);
    }

    horaire creerHoraire(int secondes) {
      horaire h = { secondes / 3600,(secondes / 60) % 60,secondes % 60 };
      return h;
    }

    void main(void) {
      horaire h = { 11,6,44 };
      afficherHoraire(h);
      printf("\n");
      afficherHoraire(creerHoraire(45321));
      printf("\n");
    }

    Typedef2.c - Typedef2.exe
    • Définition d'une struct et déclaration d'un type horaire au moyen d'un typedef portant sur cette struct
      • Attention : pas de struct nommée horaire -> impossibilité d'écrire struct horaire
      • Disparition de l'utilisation obligatoire du mot réservé "struct"
    • Deux fonctions avec paramètre de type horaire pour la première et retour de type horaire pour la seconde
    • Un programme principal de test
    11:06:44
    12:35:21

enum

  • Possibilité de déclarer des énumérations de constantes entières
    • Syntaxe sans déclaration explicite de valeur
      enum {
        CONSTANTE_1,
        CONSTANTE_2,
        ...
        CONSTANTE_N };
      Valeurs données automatiquement à partir de zéro et avec incrément de 1 à chaque nouvelle constante
    • Possibilté de donner explicitement des valeurs en utilisant l'affectation
      • Si pas de valeur explicite à la première constante, affectation automatique de la valeur zéro
      • Si pas de valeur explicite à une constante autre que la première constante, affectation de 1+valeur de la constante précédente
      • Exemple
    • #include <stdio.h>

      enum {
        A1,
        A2,
        A3,
        A4
      };

      enum {
        B1 = 8,
        B2,
        B3,
        B4
      };

      enum {
        C1 = 7,
        C2,
        C3 = -3,
        C4
      };

      void main(void) {
        printf("%3d%3d%3d%3d\n", A1, A2, A3, A4);
        printf("%3d%3d%3d%3d\n", B1, B2, B3, B4);
        printf("%3d%3d%3d%3d\n", C1, C2, C3, C4);
      }

      Enum1.c - Enum1.exe
      • Déclaration de constantes via enum
      • Trois scenarii de définition des valeurs suivant celles qui sont renseignées ou non
         0  1  2  3
         8  9 10 11
         7  8 -3 -2
    • Intérêts
      • "Vraies" constantes
      • Regroupement explicite des constantes liées à une même problématique
      • Déclaration plus simple de lots de constantes devant avoir des valeurs différentes
      • ...
  • Possibilité de créer des énumérations possèdant un nom de type
    • Syntaxe
      enum nomType {
        CONSTANTE_1,
        CONSTANTE_2,
        ...
        CONSTANTE_N };
    • Intérêts
      • Qualification des informations par les noms des variables et des constantes qui les contiennent mais aussi par les noms des types de ces variables et de ces constantes -> code plus expressif
      • ...
    • Exemple

      #include <stdio.h>
      #include <stdlib.h>

      enum couleur {
        ROUGE = 4,
        VERT = 34,
        BLEU = 23,
        JAUNE = 11
      };

      enum couleur couleurAuSort(void) {
        switch (rand() % 4) {
          case 0: {
            return ROUGE;
            break; }
          case 1: {
            return VERT;
            break; }
          case 2: {
            return BLEU;
            break; }
          default: {
            return JAUNE;
            break; }
        }
      }

      void afficherCouleur(enum couleur coul) {
        switch (coul) {
          case ROUGE: {
            printf("Rouge");
            break; }
          case VERT: {
            printf("Vert");
            break; }
          case BLEU: {
            printf("Bleu");
            break; }
          case JAUNE: {
            printf("Jaune");
            break; }
          default: {
            printf("Couleur non definie");
            break; }
        }
      }

      void main(void) {
        srand(4);
        printf("%3d%3d%3d%3d\n", ROUGE, VERT, BLEU, JAUNE);
        enum couleur coul = couleurAuSort();
        afficherCouleur(coul);
        printf("\n");
        printf("%zu %zu\n",sizeof(enum couleur),sizeof(coul));
        coul = 1;
        afficherCouleur(coul);
        printf("\n");
      }

      Enum2.c - Enum2.exe
      • Déclaration d'un enum pour quatre constantes donnant des codes numériques associés à quatre couleurs
      • Deux fonctions utilisant le type enum couleur en type retour pour la première, en type de paramètre pour un paramètre pour la seconde
      • Un programme principal de test
      • Attention
        • Non définition d'un type qui ne peut prendre que les valeurs définies dans l'énumération c'est à dire non définition d'un véritable type énumération
        • Type int en sous-main pouvant prendre n'importe quelle valeur stockable dans un int
       4 34 23 11
      Jaune
      4 4
      Couleur non definie
  • Possibilité de créer un type correspondant à une énumération en utilisant le typedef
    • Syntaxe
      typedef enum {
        CONSTANTE_1,
        CONSTANTE_2,
        ...
        CONSTANTE_N } nomType;
    • Intérêts
      • Les mêmes que ci-dessus avec en plus la suppression de l'obligation d'indiquer explicitement la nature "enum" de l'item manipulé
    • Exemple

      #include <stdio.h>
      #include <stdlib.h>

      typedef enum {
        ROUGE = 4,
        VERT = 34,
        BLEU = 23,
        JAUNE = 11
      couleur;

      couleur couleurAuSort(void) {
        switch (rand() % 4) {
          case 0: {
            return ROUGE;
            break; }
          case 1: {
            return VERT;
            break; }
          case 2: {
            return BLEU;
            break; }
          default: {
            return JAUNE;
            break; }
        }
      }

      void afficherCouleur(couleur coul) {
        switch (coul) {
          case ROUGE: {
            printf("Rouge");
            break; }
          case VERT: {
            printf("Vert");
            break; }
          case BLEU: {
            printf("Bleu");
            break; }
          case JAUNE: {
            printf("Jaune");
            break; }
          default: {
            printf("Couleur non definie");
            break; }
        }
      }

      void main(void) {
        srand(4);
        printf("%3d%3d%3d%3d\n", ROUGE, VERT, BLEU, JAUNE);
        couleur coul = couleurAuSort();
        afficherCouleur(coul);
        printf("\n");
        printf("%zu %zu\n", sizeof(couleur), sizeof(coul));
        coul = 1;
        afficherCouleur(coul);
        printf("\n");
      }

      Enum3.c - Enum3.exe
      • Mêmes remarques que Enum2.c
       4 34 23 11
      Jaune
      4 4
      Couleur non definie