HOWTO · C

Comment utiliser typedef enum en C

Cet article présente comment utiliser typedef enum en C, en explique les avantages et fournit des exemples clairs. Apprenez à améliorer la lisibilité et la maintenabilité du code avec typedef enum, et découvrez comment l'utiliser dans les structs. Que vous soyez débutant ou que vous cherchiez à perfectionner vos compétences, ce guide vous aidera à naviguer facilement parmi les enums en C.

Sur cette page

En C, un enum déclare des constantes entières nommées, et typedef peut donner au type enum un nom plus court. Utilisez les noms pour rendre les valeurs d’état et d’options plus faciles à lire, puis traitez ces valeurs explicitement chaque fois que des entrées ou des données stockées peuvent provenir de l’extérieur de votre programme. Un enum améliore la clarté, mais il ne valide pas automatiquement chaque valeur affectée à une variable.

Définir un enum et attribuer des valeurs

Un énumérateur sans valeur explicite commence à 0 ; chaque énumérateur suivant vaut un de plus que la valeur précédente. Par exemple, enum { MONDAY, TUESDAY, WEDNESDAY }; attribue 0, 1 et 2. Vous pouvez attribuer des valeurs explicitement lorsqu’elles doivent correspondre à un format, un protocole ou un ensemble stable de codes existant : enum Status { STATUS_READY = 1, STATUS_RUNNING = 4, STATUS_DONE = 8 };. Après une valeur explicite, la valeur implicite suivante vaut un de plus que cette valeur.

Les noms tels que STATUS_READY sont des constantes entières. Ce ne sont pas des variables. Une variable enum peut se voir attribuer une valeur différente ultérieurement, et C ne la limite généralement pas aux énumérateurs énumérés dans sa déclaration. Considérez les valeurs provenant d’entrées, de fichiers ou d’autres sources externes comme des données à vérifier avant de les utiliser.

Créer un alias typedef pour un enum

Une étiquette enum et un alias typedef sont des noms liés mais distincts. Avec enum State { ... };, une déclaration utilise enum State. Un typedef peut introduire l’alias plus court State, permettant des déclarations telles que State current;. L’alias fait référence au même type ; typedef ne crée pas un type distinct. L’écriture combinée typedef enum State { ... } State; déclare l’étiquette et l’alias ensemble.

Cet exemple demande un entier, vérifie que la lecture réussit et valide la valeur avant de la convertir en State et de la stocker dans le champ de Job. Saisissez 2 pour voir le chemin de réussite. Le programme affiche l’invite et la valeur répétée sur la même ligne, puis le switch affiche Running. Si la lecture échoue ou si le nombre ne fait pas partie des trois états pris en charge, le programme affiche un message et s’arrête avant la conversion.

#include <stdio.h>

typedef enum State {
    STATE_READY = 1,
    STATE_RUNNING = 2,
    STATE_DONE = 3
} State;

typedef struct Job {
    State state;
} Job;

int main(void) {
    int input;
    printf("Input: ");
    if (scanf("%d", &input) != 1) {
        puts("Could not read an integer.");
        return 0;
    }
    printf("%d\n", input);

    if (input != STATE_READY && input != STATE_RUNNING && input != STATE_DONE) {
        puts("Unsupported state.");
        return 0;
    }

    Job job = { (State)input };
    switch (job.state) {
        case STATE_READY:
            puts("Ready");
            break;
        case STATE_RUNNING:
            puts("Running");
            break;
        case STATE_DONE:
            puts("Done");
            break;
        default:
            puts("Unsupported state.");
            break;
    }

    return 0;
}
Input: Could not read an integer.

Utiliser un type enum dans un struct

Le struct Job ci-dessus stocke son état dans un champ State. Cela conserve l’état à côté des autres données qui décrivent une tâche, tandis que les constantes enum rendent les affectations et les cas de switch lisibles. Vous pouvez également déclarer le champ avec l’étiquette sous la forme enum State state; si vous choisissez de ne pas définir d’alias typedef.

Un struct n’ajoute aucune validation au champ. Si la valeur provient d’une source susceptible de fournir un nombre non pris en charge, vérifiez-la avant de vous y fier. La branche default donne au programme une réponse définie lorsque la valeur stockée ne correspond à aucun des états nommés. Si une application particulière nécessite des garanties plus strictes, validez à la frontière où la valeur entre dans le programme et gardez ce contrôle près de l’affectation.

Choisir les valeurs d’un enum et les utiliser en toute sécurité

Utilisez des valeurs implicites lorsque les constantes sont des étiquettes internes et que leur représentation numérique n’a pas d’importance. Attribuez les valeurs explicitement lorsqu’une autre interface exige des nombres précis, et gardez ces attributions stables si les données sont conservées ou échangées. Dans les deux cas, les constantes nommées communiquent l’intention mieux que les littéraux entiers inexpliqués et donnent aux mainteneurs un seul endroit où voir les étiquettes disponibles.

Ces avantages ne rendent pas les variables enum en lecture seule et ne garantissent pas qu’elles ne contiennent que des énumérateurs nommés. Une variable peut changer pendant l’exécution, et un cast ou une entrée externe peut produire une valeur sans nom correspondant. Utilisez un switch avec une branche default, ou validez la valeur par rapport aux énumérateurs acceptés avant de la traiter. Cela empêche des données inattendues de suivre silencieusement un chemin prévu pour un état connu.

En résumé, déclarez l’enum pour les constantes nommées, ajoutez un alias typedef lorsqu’il rend les déclarations plus claires, et utilisez le type résultant partout où l’état a sa place, y compris les champs de struct et les paramètres de fonction. Ne choisissez des valeurs numériques explicites que lorsque les nombres font partie d’une exigence, et gardez la validation séparée de la commodité de nommage qu’offrent les enums.