IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Les enums et leurs utilités ?


Sujet :

C

  1. #1
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut Les enums et leurs utilités ?
    Bonjour,
    je suis curieux, je connaissais les enum, mais j'avais jamais vraiment utilisé, mais je me demandais à quoi ça sert de les utiliser ?
    Je vois la simplicité si on veut faire une liste de definition, mais ça revient au même qu'un simple define.

    Et si je fais ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    enum mois_en_r { janvier = 1, fevrier, mars, avril, septembre = 9, octobre, novembre, decembre } a;
    printf ("%d", a);
    Que représente a ? un bloc mémoire quelconque ? et pourquoi attribuer les élements à la variable 'a', quel peut en être l'intérêt ?

    merci d'avance !

  2. #2
    Membre éclairé
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Points : 807
    Points
    807
    Par défaut
    Oui, tu peux te débrouiller pour faire la même chose qu'une énumération avec une suite de #define.
    C'est surtout une question de lecture du code (lisibilité), ça permet de regrouper plusieurs constantes comme étant un type, qui peut prendre certaines valeurs. Définir une énumération ne définit pas un domaine de définition mais des constantes symboliques représentant des entiers (de type int je crois).

  3. #3
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    - Par un enum, on définit des symboles représentant des constantes entières. On peut aussi faire la même chose avec #define.
    Une variable de type enum est d'un type entier. Le type exact peut être différent selon la définition de l'enum ou/et le compilateur utilisé.
    Comme on ne connait pas à priori le type exact (entier) d'une variable de type enum, on a un comportement imprévisible sur ce genre de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    enum mois_en_r x;
    scanf("%d", &x);
    Les constantes définies dans l'enum ont le type int

    - Le lecteur est également en droit de s'attendre à ce que l'enum ne soit pas un fourre-tout mais que les termes de l'enum soient liés logiquement entre eux. On voit difficilement la logique d'un programmeur dans l'enum suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef enum {rouge, lundi, bonjour, erreur} uneEnum;
    - Le C n'impose pas que la valeur d'une variable de type enum soit l'un des membres de l'enum : il n'y a pas de vérification de ce fait.
    (L'enum que tu proposes pour coder les mois en "r" risque de ne pas pouvoir être utilisée comme tu le penses car rien n'interdit à une variable enum de ce type d'avoir la valeur 8 et on ne peux savoir si une valeur fait partie d'une enum sans faire des tests sur chaque valeur possible de l'enum.)

    - L'utilité d'une enum est donc essentiellement documentaire. Bien que rien ne l'impose, le lecteur attend lui qu'une variable de type enum prenne comme valeur l'une des constantes du type enum. Il suppose implicitement que c'est pour cela que le programmeur a pris la précaution de définir une enum.
    Ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    //.h
    typedef enum {rouge, orange, jaune, vert, bleu} Couleur;
    void fonc(Couleur x);
    //.c
    Couleur c = orange;
    fonc(c);
    fonc(rouge);
    est déjà plus parlant sur les intentions du programmeur que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //.h
    void fonc(int x);
    //.c
    fonc(1);
    fonc(0);
    ou même que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //.h
    #define rouge 0
    #define orange 1
    void fonc(int x);
    //.c
    int c = orange;
    fonc(c);
    fonc(rouge);

  4. #4
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Tout ça vient du tutoriel qu'il y a sur le site
    http://c.developpez.com/cours

    ok, je vais donc changer quelques de mes define par des enum.

    merci

  5. #5
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    Avantage non négligeable, dans un débogueur un enum affichera un label et non pas un entier. C'est quand même plus parlant de voir affiché "mercredi", "timeout" ou "rouge" que 7, 15 ou 32.

    La gestion des switches est également beaucoup plus parlante avec des enums qu'avec des entiers. Et là encore, l'enum est mieux que le define, puisqu'il n'autorise comme valeurs à tester que ce qui est défini sa liste.

    A+

    Pfeuh

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par pfeuh Voir le message
    Et là encore, l'enum est mieux que le define, puisqu'il n'autorise comme valeurs à tester que ce qui est défini sa liste.
    Non, comme on l'a démontré plus haut...

    (Cela est vrai lors du passage à une fonction, cela est faux lors d'une utilisation dans le même bloc... je crois. Mais je n'en utilise jamais)

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 400
    Points : 23 778
    Points
    23 778
    Par défaut
    Il y a encore trois avantages :

    — Ça permet d'associer une sémantique à la définition du type, comme sous-entendu dans les autres commentaires. Ex : le débogueur sait effectivement de quoi il s'agit et peut afficher les étiquettes en conséquence ;
    — La portée d'une « enum » est limitée au bloc dans lequel elle est déclarée, contrairement à une palanquée de #define qu'il faut explicitement « indéfinir » (avec #undef) si on veut limiter sa portée ;
    — Il est très facile d'insérer un nouveau terme au milieu de la liste, si besoin, et le reste de la suite sera automatiquement re-numérotée, ce qui peut s'avérer assez fastidieux avec une liste de #define.

    Je pense que c'est cela qui, à l'usage, distingue l'utilisation des #define et des énumérations : au sein d'un même programme, on préfère les « enum » pour limiter leur portée et favoriser la signification de chaque option, et on utilise majoritairement les #define dans les fichiers « *.h » publics pour garantir la cohérence des numéros attribués à travers le temps et les différentes versions.

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Je pense que c'est cela qui, à l'usage, distingue l'utilisation des #define et des énumérations : au sein d'un même programme, on préfère les « enum » pour limiter leur portée et favoriser la signification de chaque option, et on utilise majoritairement les #define dans les fichiers « *.h » publics pour garantir la cohérence des numéros attribués à travers le temps et les différentes versions.
    Oui..

    Cependant, une construction d'un .h tel que

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define PREMIER 0
    #define SECOND (PREMIER+1)
    #define TROSIEME (SECOND+1)
    ...

    ou

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define PREMIER 0
    #define SECOND (PREMIER+1)
    #define TROSIEME (PREMIER+2)
    ...

    permet une insertion et une maintenance tout aussi simple...

    Par contre effectivement la portée est moins limitée, et l'afichage d'un libellé impossible..

  9. #9
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Non, comme on l'a démontré plus haut...
    Il faut activer les bons warnings. Dans l'exemple ci-dessous, le CASE 48 ne passe pas et l'absence du CASE STATE_EPILOGUE non plus. Je n'ai aucune idée sur ce qu'en dit la norme et si ces warning sont sur tous les compilos.

    Citation Envoyé par souviron34 Voir le message
    [I]Cela est vrai lors du passage à une fonction
    Le bout de programme ci-dessous montre le contraire. On peut passer n'importe quel entier à la fonction checkState, qui est pourtant sensée prendre un STATE. Dans l'exemple, on passe l'entier 48 sans problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include <stdio.h>
     
    typedef enum {STATE_PROLOGUE=1, STATE_ACTIVE=2, STATE_EPILOGUE=3} STATE;
     
    int checkState(STATE state)
    {
        int retval;
     
        switch(state)
        {
            case STATE_PROLOGUE:
            case STATE_ACTIVE:
            /*case STATE_EPILOGUE:
                retval = state;
                break;*/
            case 48:
                retval = state;
                break;
            default:
                retval = -1;
                break;
        }
        return retval;
    }
     
    int main(void)
    {
        STATE current_state;
     
        printf ("sizeof state :%u\n", sizeof current_state);
        current_state = STATE_PROLOGUE;
        printf("%i\n" ,checkState(current_state));
        current_state = STATE_ACTIVE;
        printf("%i\n" ,checkState(current_state));
        current_state = STATE_EPILOGUE;
        printf("%i\n" ,checkState(current_state));
        current_state = 48;
        printf("%i\n" ,checkState(current_state));
        current_state = 49;
        printf("%i\n" ,checkState(current_state));
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    D:\faller\languages\C\codeblocks\dummy\main.c||In function 'checkState':|
    D:\faller\languages\C\codeblocks\dummy\main.c|9|warning: enumeration value 'STATE_EPILOGUE' not handled in switch|
    D:\faller\languages\C\codeblocks\dummy\main.c|16|warning: case value '48' not in enumerated type 'STATE'|
    ||=== Build finished: 0 errors, 2 warnings ===|
    Images attachées Images attachées  

  10. #10
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Les compilateurs sont futés et émettent souvent des warnings pour les choses qui leur semblent bizarre, insolite ou pouvant cacher une erreur d'inattention du programmeur (comme par exemple sur ce genre de code if(i=0)...)

    L'avertissement précédent est de ce type :
    D:\faller\languages\C\codeblocks\dummy\main.c|9|warning: enumeration value 'STATE_EPILOGUE' not handled in switch|
    dont en toute rigueur, il aurait pu faire l'économie puisque le switch comportait un default explicite, mais le principe de précaution est visiblement appliqué par ton compilateur.

    Ce qu'il faut retenir, c'est
    - qu'il n'y a pas de contrôle de la "validité" de la valeur d'une variable enum à l'exécution.
    - les variables enum ont un type entier mais on n'en sait pas plus (on ne sait pas sa taille ni même si il est signé ou non et il n'est pas forcément le même pour toutes les enum d'un même programme). On doit dans certains cas tenir compte de ce fait (cf message #3)
    - les constantes d'une enum ont le type int

  11. #11
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    je vais rester sur du define en faite je crois.
    Ce n'est pas une variable locale que je cherche, mais plutôt des valeurs que le compilateur applique lors de la compilation.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CLOB/BLOB] Quelles sont leurs utilités ?
    Par maximus001ma dans le forum DB2
    Réponses: 8
    Dernier message: 01/02/2006, 15h30
  2. Réponses: 1
    Dernier message: 20/12/2005, 19h50
  3. Lister les process avec leurs arguments
    Par jamfr73 dans le forum MFC
    Réponses: 5
    Dernier message: 23/12/2004, 10h54
  4. Réponses: 4
    Dernier message: 13/12/2004, 20h37
  5. Les utilitaires utile et leur utilités
    Par netah25 dans le forum Autres Logiciels
    Réponses: 5
    Dernier message: 27/10/2004, 12h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo