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.