📘 Kapitel 7 · Unit 31 von 36

enum
Lesbare Konstanten

Magic Numbers vermeiden · typedef enum · Ampelsteuerung · explizite Werte · Typsicherheit

31 / 36 Units
Ömer
Kapitel 7: Praxis & Fortgeschritten ~100 Min. Theorie + Simulator + Quiz + Spickzettel
Ömer
Ömer sagt:

Stell dir vor, du liest Code und siehst if (status == 2). Was bedeutet 2? Ein Fehler? Ein Zustand? Mit enum schreibst du stattdessen if (status == GELB) — sofort klar! Das ist der Kern von enum: lesbarer Code statt kryptischer Zahlen.

1. Was ist enum?

Ein enum (Enumeration = Aufzählung) ist ein Datentyp in C, der einer Menge von benannten ganzzahligen Konstanten Namen gibt. Das Ziel: "Magic Numbers" im Code zu ersetzen und den Code lesbarer zu machen.

❌ Ohne enum – Magic Numbers

Was bedeutet diese 2? Fehler? Status? Farbe?

if (ampel == 2) {
  printf("Gruen!\n");
}

✅ Mit enum – sofort verständlich

GRUEN erklärt sich selbst!

if (ampel == GRUEN) {
  printf("Gruen!\n");
}

Grundsyntax

enum_syntax.cC
/* Deklaration */
enum Farbe { ROT, GELB, GRUEN };

/* Standardwerte: ROT=0, GELB=1, GRUEN=2 */

int main() {
    enum Farbe ampel = ROT;   /* ampel hat den Wert 0 */
    printf("%d\n", ampel);          /* gibt 0 aus */
    return 0;
}

Automatische Nummerierung

Der erste Eintrag bekommt standardmäßig den Wert 0, jeder weitere wird um 1 erhöht. enum { A, B, C } bedeutet: A=0, B=1, C=2.

2. typedef enum – kürzere Schreibweise

Mit enum Farbe muss man beim Variablentyp immer das Schlüsselwort enum davor schreiben. Mit typedef entfällt das:

typedef_enum.cC
/* Ohne typedef – umständlich */
enum Farbe { ROT, GELB, GRUEN };
enum Farbe ampel = ROT;   /* "enum" muss immer dabei sein */

/* Mit typedef – viel kürzer */
typedef enum { ROT, GELB, GRUEN } Farbe;
Farbe ampel = ROT;           /* kein "enum" nötig! */

In der Praxis wird fast immer typedef enum verwendet, weil es den Code kürzer und lesbarer macht. Das ist der empfohlene Stil.

3. Praktisches Beispiel – Ampelsteuerung

Ein klassisches Anwendungsbeispiel: eine Ampel hat genau drei Zustände. Mit enum sind sie klar bennant und alle switch-Cases vollständig abgedeckt:

ampel.cC
#include <stdio.h>

typedef enum { ROT, GELB, GRUEN } Ampelfarbe;

void zeige_ampel(Ampelfarbe farbe) {
    switch (farbe) {
        case ROT:
            printf("STOP – Rot!\n");
            break;
        case GELB:
            printf("Achtung – Gelb!\n");
            break;
        case GRUEN:
            printf("Fahrt frei – Gruen!\n");
            break;
    }
}

int main() {
    Ampelfarbe a = GRUEN;
    zeige_ampel(a);      /* Fahrt frei – Gruen! */
    zeige_ampel(ROT);    /* STOP – Rot!         */
    return 0;
}
▶ Ausgabe
Fahrt frei – Gruen! STOP – Rot!

4. enum mit expliziten Werten

Man kann jedem enum-Eintrag einen eigenen Wert zuweisen. Nicht zugewiesene Einträge zählen ab dem letzten expliziten Wert weiter:

enum_werte.cC
/* Explizite Werte – sinnvoll für Fehlercodes */
typedef enum {
    NIEDRIG  = 1,
    MITTEL   = 5,
    HOCH     = 10
} Prioritaet;

/* HTTP-Status-ähnliches Muster */
typedef enum {
    OK              = 0,
    DATEI_FEHLER    = 1,
    SPEICHER_FEHLER = 2,
    NETZ_FEHLER     = 3
} Fehler;

int main() {
    Fehler code = DATEI_FEHLER;
    printf("Fehlercode: %d\n", code);  /* gibt 1 aus */

    Prioritaet p = HOCH;
    printf("Prioritaet: %d\n", p);  /* gibt 10 aus */
    return 0;
}
▶ Ausgabe
Fehlercode: 1 Prioritaet: 10

Wann explizite Werte sinnvoll sind

  • Fehlercodes, die an externe Systeme übergeben werden
  • Wenn die Zahlenwerte eine inhärente Bedeutung haben (HTTP-Codes: 200, 404, 500)
  • Wenn Kompatibilität mit gespeicherten Werten (Datei/Datenbank) nötig ist
  • Bei Prioritätssystemen mit Abständen (1, 5, 10 erlaubt späteres Einfügen)

5. enum in if-Bedingungen und Vergleichen

Da enum-Werte Ganzzahlen sind, funktionieren alle arithmetischen Vergleiche. Das macht enum ideal für Prioritätssysteme:

enum_vergleich.cC
#include <stdio.h>

typedef enum { NIEDRIG=1, MITTEL=5, HOCH=10 } Prioritaet;

void pruefe_prio(Prioritaet p) {
    if (p >= HOCH) {
        printf("ALARM: Hohe Prioritaet!\n");
    } else if (p >= MITTEL) {
        printf("Mittlere Prioritaet\n");
    } else {
        printf("Niedrige Prioritaet\n");
    }
}

int main() {
    pruefe_prio(HOCH);    /* ALARM: Hohe Prioritaet!  */
    pruefe_prio(MITTEL);  /* Mittlere Prioritaet       */
    pruefe_prio(NIEDRIG); /* Niedrige Prioritaet       */
    return 0;
}
▶ Ausgabe
ALARM: Hohe Prioritaet! Mittlere Prioritaet Niedrige Prioritaet

6. Wochentage-Beispiel (vollständig)

Ein vollständiges Beispiel: Wochentage als enum, beginnend bei 1 (Montag). Alle folgenden Werte werden automatisch weitergezählt — DI=2, MI=3 usw.

wochentage.cC
#include <stdio.h>

/* MO=1, dann DI=2, MI=3, DO=4, FR=5, SA=6, SO=7 automatisch */
typedef enum { MO=1, DI, MI, DO, FR, SA, SO } Wochentag;

int ist_wochenende(Wochentag t) {
    switch (t) {
        case SA:
        case SO:
            return 1;   /* Wochenende */
        default:
            return 0;   /* Wochentag */
    }
}

int main() {
    Wochentag tag;
    for (tag = MO; tag <= SO; tag++) {
        if (ist_wochenende(tag)) {
            printf("Tag %d: Wochenende!\n", tag);
        } else {
            printf("Tag %d: Arbeitstag\n", tag);
        }
    }
    return 0;
}
▶ Ausgabe
Tag 1: Arbeitstag Tag 2: Arbeitstag Tag 3: Arbeitstag Tag 4: Arbeitstag Tag 5: Arbeitstag Tag 6: Wochenende! Tag 7: Wochenende!

7. Häufige Fehler

FehlerProblemLösung
enum == int direktKompiliert, aber schlechter Stil und fehleranfälligEnum-Namen verwenden, nicht Rohzahlen
Gleiche Namen in 2 enumsNamenskonflikt — Compiler-FehlerPräfix benutzen: AMPEL_ROT, STATUS_ROT
Startet bei 0, nicht 1Off-by-One wenn als Array-Index verwendetErstes Element auf 1 setzen oder explizit mit =0 ankern
Strings in enumNicht möglich! enum { "ROT" } geht nichtLookup-Array: const char *namen[] = {"ROT","GELB","GRUEN"};
Kein default in switchUngültige enum-Werte bleiben unbehandeltImmer default: mit Fehlermeldung

✅ Strings aus enum-Werten – Lookup-Array-Muster

Da enum keine Strings speichern kann, nutzt man ein paralleles Array:

typedef enum { ROT, GELB, GRUEN } Ampelfarbe;
const char *namen[] = { "Rot", "Gelb", "Gruen" };
printf("%s\n", namen[GELB]); /* gibt "Gelb" aus */

⚡ Code-Simulator

Schreibe C-Code links und führe ihn aus – der Simulator zeigt printf-Ausgaben sofort:

C Simulator – Unit 31
▶ Ausgabe
– Klicke auf AUSFÜHREN –
Ömer
Ömer sagt:

Ändere die enum-Werte oder füge einen neuen Zustand hinzu. Probiere auch printf("%d", GRUEN) aus — du siehst, dass GRUEN intern die Zahl 2 ist!

🎯 Wissens-Quiz

Frage 1
Was ist der Standardwert des ersten enum-Eintrags wenn kein expliziter Wert angegeben wird?
A1
B0
C-1
DUndefiniert
Frage 2
Welche Syntax ist korrekt für typedef enum?
Aenum typedef { A, B } Name;
Btypedef enum { A, B } Name;
Ctypedef { A, B } enum Name;
Denum Name typedef { A, B };
Frage 3
Gegeben: enum { X=5, Y, Z }; — welchen Wert hat Y?
A5
B6
C1
D0
Frage 4
Kann man enum-Werte mit switch-case verwenden?
ANein, switch funktioniert nur mit int
BJa, und es ist sogar ideal — alle Fälle sind klar benannt
CNur mit einem expliziten Cast zu int
DNur wenn typedef verwendet wurde
Frage 5
Was ist ein Vorteil von enum gegenüber #define-Konstanten?
A#define ist immer besser
Benum erlaubt Strings als Werte
CTypsicherheit und bessere Debugging-Unterstützung
Denum läuft schneller zur Laufzeit
Frage 6
Was gibt dieses Programm aus? enum { A, B, C }; printf("%d", C);
A0
B1
C2
D3
Frage 7
Welches Schlüsselwort macht enum-Namen direkt verwendbar, ohne das Wort "enum" davor schreiben zu müssen?
Adefine
Bstruct
Ctypedef
Dextern
Frage 8
Wozu dient enum hauptsächlich in C?
AZum Speichern von Zeichenketten
BZur Speicherverwaltung
CFür mathematische Berechnungen
DLesbare benannte Konstanten statt Magic Numbers

📋 Spickzettel

enum Syntax
enum Name { A, B };Ohne typedef
typedef enum { A, B } Name;Mit typedef (empfohlen)
Name var = A;Variable deklarieren
printf("%d", var);Zahlenwert ausgeben
Automatische Nummerierung
{ A, B, C }A=0, B=1, C=2
{ A=1, B, C }A=1, B=2, C=3
{ A=5, B, C }A=5, B=6, C=7
{ A=0, B=10, C=20 }Explizite Werte
Anwendungsmuster
switch (var) { case A: }Ideal für switch
if (var >= HOCH)Vergleich möglich
namen[var]String via Lookup-Array
for (v=A; v<=C; v++)Über enum iterieren
enum vs. #define
enumTypsicher, debuggable
#defineTextersatz, kein Typ
enum: ZuständeAmpel, Wochentage…
#define: ZahlenPI, BUFFER_SIZE…

✅ Checkliste Unit 31

  • Ich verstehe den Unterschied zwischen enum und Magic Numbers
  • Ich kann typedef enum korrekt deklarieren und verwenden
  • Ich weiß, wie die automatische Nummerierung funktioniert
  • Ich kann explizite Werte in einem enum vergeben
  • Ich kann enum mit switch-case und if-Bedingungen einsetzen
  • Ich kenne das Lookup-Array-Muster für Strings aus enum-Werten