13.2. Aufzählungstypen mit enum

Aufzählungstypen sind gedacht für Integer-Variablen, die nicht jeden beliebigen Wert annehmen dürfen, sondern auf eine begrenzte Anzahl von Werten beschränkt sind. Diese Werte werden über Namen angesprochen. Typische Kandidaten für solche Aufzählungen sind die Tage einer Woche, die Monate eines Jahres oder die Einheiten einer Währung. Die allgemeine Form einer enum-Anweisung lautet:


enum [Name]{Element_1, Element_2,..., Element_n} [Variablenliste];

Die Angabe des Namens für den Aufzählungstyp kann entfallen, falls eine Variablenliste angegeben wird. Allerdings können dann später neue Variablen dieses Typs nicht mehr definiert werden. Wird ein Name angegeben, dann kann auf die Variablenliste verzichtet werden, da sich später noch beliebig viele Variablen dieses Aufzählungstyps definieren lassen. Folgende Anweisung deklariert einen Aufzählungstyp mit dem Namen Wochentag:


enum Wochentag{SON, MON, DIE, MIT, DON, FRE, SAM};
/* SUN entspricht 0, SAM entspricht 6 */

Jedes Namenssymbol steht für einen ganzzahligen Wert, wobei jedes Namenssymbol um den Wert 1 größer ist als das vorhergehende; Der Anfangswert für das erste Symbol beträgt standardmäßig 0. Es besteht allerdings die Möglichkeit, in diese Abstufung der Werte durch explizite Initialisierungen einzugreifen:


enum Himmelsrichtung{NORD, OST=90, SUED=180, WEST=270};
/* NORD hat den Wert 0. Würde SUED nicht mit 180
 * initialisiert, dann hätte es automatisch den
 * Wert 91.
 */

Jede Variable des Aufzählungstyps Wochentag darf Werte im Bereich von SON bis SAM annehmen; für eine Variable des Typs Himmelsrichtung stehen genau vier Werte (von NORD bis WEST) zur Auswahl. Variablen der jeweiligen Aufzählungstypen stehen nach den beiden oben angeführten enum-Anweisungen allerdings noch nicht zur Verfügung, denn beide beschränken sich auf die Deklaration eines neuen Datentyps. Damit geben Sie dem Compiler bekannt, wie der Aufzählungstyp aufgebaut ist, reservieren aber — wie bei Deklarationen üblich — noch keinen Speicherplatz. Dazu bedarf es einer Variablendefinition. Diese können Sie gleich bei der Deklaration vornehmen, indem Sie nach der schließenden geschweiften Klammer den Namen einer oder mehrerer Variablen angeben. Es ist aber ohne weiteres möglich, die Variablen im Anschluß an die Deklaration eines Aufzählungstyps zu definieren:


/* definiert die Variable Heute
 * vom Aufzählungstyp Wochentag
 */
enum Wochentag Heute;

An die Variable Heute kann jederzeit eines der 7 Elemente aus der Deklarationsliste zugewiesen werden:


/* MON ist keine Zeichenkette, sondern
 * steht für den Wert 1
Heute = MON;
/* In C ist leider auch die Zuweisung eines
 * beliebigen int-Werts erlaubt, z.B.
 * Heute = 20
 * in C++ sind demgegenüber nur Werte aus der
 * Deklarationsliste zulässig, andere führen zu
 * einer Fehlermeldung
 */

Die Elemente einer Aufzählungsliste können überall dort verwendet werden, wo int-Konstanten zulässig sind:


/* #include und #define-Anweisungen */
.
enum Wochentag{SON, MON, DIE, MIT, DON, FRE, SAM};
typedef enum Wochentag wtag;
/* der Aufzählungstyp Wochentag steht ab sofort
 * als eigenständiger Datentyp wtag zu Verfügung
 */

int main(void){

wtag Heute = FRE;
long lArray[5]={0,1,2,3,4};

/* DIE kann anstelle der Integer-
 * Konstanten 2 verwendet werden
 */
printf("Wert von lArray[2]: %ld\n", lArray[DIE]);

/* falsch hingegen ist: */
printf("Heute ist %s\n", Heute);
/* FRE ist keine Zeichenkette,
 * sondern vom Typ int! */

return 0;
}

Dieses Fragment demonstriert die Anwendung von typedef auf einen Aufzählungstyp. Nach der Bereitstellung des neuen Datentyps wtag entfällt die Angabe des Schlüsselworts enum bei der Defintion einer Variablen; statt


enum Wochentag Heute;

kann einfach


wtag Heute;

angegeben werden.

Wie schon bei typedef empfiehlt es sich auch bei enum, die Deklaration eines Aufzählungstyps noch vor main() anzusiedeln. Einzelne Variablen eines solcherart eingerichteten Typs sollten dann nach Möglichkeit — wie bei Variablen generell üblich — lokal definiert werden. Sollten Sie mehrere Aufzählungstypen in einem Programm benötigen, dann müssen Sie unterschiedliche Namen für die Elemente der verschiedenen Aufzählungslisten benutzen, da der Compiler sonst ja nicht wissen kann, welche Konstante im Einzelfall gerade gemeint ist und mit einer Fehlermeldung reagiert:


enum DayOfWeek{SU, MO, TU, WE, TH, FR, SA};
enum Himmelsrichtung{NO, OS=90, SU=180, WE=270};
/* Fehler, da sowohl DayOfWeek als auch
 * Himmelsrichtung über die Werte SU und
 * WE verfügen!
 */

Der Gültigkeitsbereich von Konstanten einer Aufzählungsliste hängt vom Ort der Deklaration eines enum-Typs ab: Findet sie vor main() statt, dann sind jene global gültig, andernfalls innnerhalb des Anweisungsblocks, in dem die Deklaration stattfand. Wie schon bei Variablen, kann auch eine symbolische Konstante aus einer Aufzählungsliste durch eine gleichnamige lokale Variable überdeckt werden:


.
.
enum DayOfWeek{SUN, MON, TUE, WED, THU, FRI, SAT};

int main(void){

/* Diese Variable macht die Konstante WED aus
 * DayOfWeek unzugänglich
 */
int WED = 1000;

 /* printf() gibt nicht 3, sondern 1000 aus */
 printf("Wert von WED: %d\n", WED);
.
.

Diese Gefahr von Namenskonflikten können Sie ausschließen, indem Sie sich bei der Namensvergabe für Variablen an die Hungarian Notation halten und bei Aufzählungs-Konstanten der Konvention folgend nur Großbuchstaben verwenden.