enum în C

Definește un set de constante întregi cu nume, de exemplu zilele săptămânii sau stările unei comenzi.

Sintaxă
enum nume { A, B, C };              // A = 0, B = 1, C = 2
enum nume { A = 1, B = 5, C };      // C = 6
enum nume : unsigned char { ... };  // C23: tip de bază fix

Ce face enum

Un enum (enumerare) dă nume unor valori întregi. Prima constantă primește implicit 0, iar fiecare următoare cu 1 mai mult decât cea dinainte. Poți da și valori explicite; după o valoare explicită, numărătoarea continuă de la ea.

Constantele unui enum sunt vizibile direct, fără prefix (LUNI, nu zi.LUNI), așa că se obișnuiește să aibă nume unice, de multe ori cu un prefix comun. O variabilă de tip enum este un întreg, deci compilatorul nu te oprește să-i pui altă valoare.

Din C23 poți fixa tipul de bază: enum stare : unsigned char { ... }. Așa știi exact câți octeți ocupă (aici 1) și poți folosi valori care nu încap în int. Fără tip fix, compilatorul alege un tip întreg potrivit, de obicei int.

Exemple

Exemplul 1: Stările unei comenzi

Constantele primesc valorile 0, 1, 2, 3. Un switch pe un enum este ușor de citit, iar -Wall avertizează dacă uiți un caz.

#include <stdio.h>

enum stare { PLASATA, PLATITA, EXPEDIATA, LIVRATA };

const char *text_stare(enum stare s) {
    switch (s) {
        case PLASATA:   return "plasată";
        case PLATITA:   return "plătită";
        case EXPEDIATA: return "expediată";
        case LIVRATA:   return "livrată";
    }
    return "necunoscută";
}

int main(void) {
    enum stare comanda = EXPEDIATA;
    printf("Comanda este %s (cod %d)\n", text_stare(comanda), comanda);
    return 0;
}

Rezultat

Comanda este expediată (cod 2)

Exemplul 2: Valori explicite

MARTIE nu are valoare explicită, deci primește 3, adică FEBRUARIE + 1.

#include <stdio.h>

enum luna { IANUARIE = 1, FEBRUARIE, MARTIE, DECEMBRIE = 12 };

int main(void) {
    printf("IANUARIE=%d FEBRUARIE=%d MARTIE=%d DECEMBRIE=%d\n",
           IANUARIE, FEBRUARIE, MARTIE, DECEMBRIE);
    return 0;
}

Rezultat

IANUARIE=1 FEBRUARIE=2 MARTIE=3 DECEMBRIE=12

Exemplul 3: Tip de bază fix (C23)

Cu : unsigned char, fiecare valoare ocupă un singur octet, util în structuri sau fișiere binare.

#include <stdio.h>

enum culoare : unsigned char { ROSU, VERDE, ALBASTRU };
enum mare { MIC, MEDIU };

int main(void) {
    enum culoare c = VERDE;
    printf("sizeof(enum culoare) = %zu\n", sizeof(enum culoare));
    printf("sizeof(enum mare)    = %zu\n", sizeof(enum mare));
    printf("c = %d\n", c);
    return 0;
}

Rezultat

sizeof(enum culoare) = 1
sizeof(enum mare)    = 4
c = 1

Greșeli frecvente

  • Folosești același nume de constantă în două enumerări diferite. Constantele sunt în același spațiu de nume, deci compilatorul dă eroare de redefinire; folosește prefixe (STARE_, CULOARE_).
  • Te bazezi pe faptul că o variabilă enum poate avea doar valorile listate. În C, orice întreg poate fi pus în ea; verifică valorile primite din exterior.
  • Afișezi un enum cu %s. Valoarea este un întreg; pentru text ai nevoie de o funcție sau un tablou de șiruri.

Comenzi înrudite

  • switch: Alege una din mai multe ramuri după valoarea unui întreg, cu etichete case; fără break, execuția continuă în ramura următoare.
  • struct: Grupează mai multe valori de tipuri diferite într-un singur tip nou, de exemplu numele, vârsta și orașul unei persoane.
  • union: Ca un struct, dar toate câmpurile folosesc aceeași zonă de memorie, așa că la un moment dat păstrează o singură valoare.
  • typedef: Dă un nume nou, mai scurt sau mai clar, unui tip existent: o structură, un pointer sau un tip de funcție.
  • constexpr: Declară o constantă cu valoare calculată la compilare, cu tip, care poate fi folosită ca dimensiune de tablou sau în static_assert.
  • #define: Definește o macro: un nume pe care preprocesorul îl înlocuiește cu textul dat, înainte ca programul să fie compilat.