Forum: PC-Programmierung Frage zum Sinn von enum in C


von Alexander (Gast)


Lesenswert?

Hi

ich habe mich gerade in enum in C eingelesen, und muss gestehen, dass 
mir der Sinn / Anwendungszweck noch nicht so ganz klar ist. Ich dachte, 
mittels enum erstellt man (s)einen eigenen Datentyp. Was genau ist der 
Sinn und Zweck der "enumerators" innerhalb der geschweiften Klammer? Es 
wäre für mich einleuchtend, dass mittels eines enum Datentyps die 
entstandene enum Variable lediglich die Werte der "enumerators" 
innerhalb der geschweiften Klammer annehmen darf. Dem ist aber nicht so. 
Siehe folgendes Minimalbeispiel. Dort wird der enum Variable Comp4 der 
Wert der Variable test zugewiesen. Wenn das zulässig ist, wozu braucht 
man dann die enumerators? Besteht der einzige Sinn darin, dass die 
enumerators lediglich automatisch eine fortlaufende Integerzahl haben 
(0, 1, 2, etc.) und man somit nicht manuell jedes einzelne Element 
initialisieren muss?
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
int main()
5
{
6
    enum Company {Google, Facebook, Xerox, Yahoo, Ebay, Microsoft};
7
8
    int test = 10;
9
    enum Company Comp1 = Xerox;
10
    enum Company Comp2 = Google;
11
    enum Company Comp3 = Ebay;
12
13
    enum Company Comp4 = test;
14
15
    printf("%d\n%d\n%d\n%d\n",Comp1,Comp2,Comp3,Comp4);
16
    return 0;
17
}

Vielen Dank,

von Dirk B. (dirkb2)


Lesenswert?

Alexander schrieb:
> Besteht der einzige Sinn darin, dass die
> enumerators lediglich automatisch eine fortlaufende Integerzahl haben
> (0, 1, 2, etc.) und man somit nicht manuell jedes einzelne Element
> initialisieren muss?

Nicht nur.

Sie bleiben auch als Debug-Information erhalten, während ein #define 
direkt ersetzt wird.

von x^2 (Gast)


Lesenswert?

C erlaubt viel. Tipp: Die Warnungen einschalten! Dieses Beispiel wird 
einige erzeugen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Enums dienen primär dazu, für eine Folge von Integer-Zahlen Symbole zu
definieren. Diese wiederum sollen ein Programm besser verständlich
machen, da sich ein Leser unter dem Symbol Xerox mehr vorstellen kann
als unter der schnöden Firmennummer 2.

Enums stellen zwar jeweils eigene Datentypen dar, allerdings werden in C
beliebige Integer-Zahlen bei einer Zuweisung implizit konvertiert.

In C++ gibt es diese implizite Konvertierung nach enum nicht, weswegen
dort die Zeile

1
    enum Company Comp4 = test;

einen Fehler darstellt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dirk B. schrieb:

> Sie bleiben auch als Debug-Information erhalten, während ein #define
> direkt ersetzt wird.

Stimmt so mittlerweile auch nicht mehr. Mit -g3 übernimmt GCC nunmehr 
auch die Makros in die Debug-Informationen.

Allerdings weiß ein Debugger bei einer Variablen, die über einen 
enum-Typ definiert ist, dass er die möglichen Werte dieser Variablen mit 
den Namen der Enumeratoren darstellen kann; beliebige Makros wird er an 
dieser Stelle nicht freiwillig anzeigen.

Ist aber tatsächlich bei C so ziemlich der einzige Vorteil von enums. 
Außerdem kann ein Compiler eine Warnung ausgeben, wenn man einen 
enum-Ausdruck als Steuerausdruck eines "switch" benutzt und dann nicht 
für alle Enumeratoren einen Zweig hat (und auch keinen "default"-Zweig).

von Leo (Gast)


Lesenswert?

Jörg W. schrieb:
> Außerdem kann ein Compiler eine Warnung ausgeben, wenn man einen
> enum-Ausdruck als Steuerausdruck eines "switch" benutzt und dann nicht
> für alle Enumeratoren einen Zweig hat (und auch keinen "default"-Zweig).

Wer allerdings einen enum benutzt um Error-Codes (große Anzahl an 
Enumeratoren) aus einer Funktion zurück zugeben, wird froh sein wenn er 
diese Compiler-Option deaktivieren kann. Denn es könnte durchaus sein, 
dass nur einige Enumeratoren (Error-Codes) ausgewertet werden sollen.

Gruß Leo

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Leo schrieb:
> Denn es könnte durchaus sein, dass nur einige Enumeratoren (Error-Codes)
> ausgewertet werden sollen.

Wenn man sich da völlig sicher ist (und nur dann würde man die Warnung 
ausschalten), kann man natürlich auch einem Zweig ein "default" mit 
draufdrücken. Wenn man paranoid ist, schreibt man noch ein 
``assert("Unexpected return value" == NULL)'' in diesen Zweig. :-)

von Daniel A. (daniel-a)


Lesenswert?

Enums sind fortlaufende Constanten, das ist für vieles nützlich. 
Besonders zusammen mit designated initialisern finde ich es praktisch:
1
const char* info[] = {
2
  [Google]    = "Don't be evil - das war mal.", 
3
  [Facebook]  = "Früher mal beliebter social Media Provider - wir wollen dein Gesicht & Leben!", 
4
  [Xerox]     = "Wir erfanden die Maus & die GUI - dann hat Steve es als seins verkauft...",
5
  [Yahoo]     = "Wir hatten deine Mails und ersetzten deine Suche - die paar breaches waren doch nicht so schlimm...", 
6
  [Microsoft] = "Auf jedem neuen PC - Nein, du wirst uns nicht mehr los, jetzt zahl schon deine Office Lizenzgebühren und gib auch uns deine Daten.",
7
};

So kann man auch mehrere separate Listen mit einfach verständlicher 
Indexierung haben, wenn z.B. gewisse Dinge nicht in das selbe struct 
sollen, usw..

von Alexander (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
vielen Dank für eure Rückmeldung.

Daraus schließe ich:
Folgende Linie Code
1
enum Company Comp4 = test;
widerspricht dem eigentlichen Sinn der Benutzung von enums (unter 
Berücksichtigung meines restlichen Programms). Zulässig im Compiler 
bedeutet nicht zwangsläuft angedacht in der Programmiersprache.

Gedacht ist, dass man eigentlich die enumerations in der Geschweiften 
Klammer verwenden soll.

Gruß,

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Alexander schrieb:
> Gedacht ist, dass man eigentlich die enumerations in der Geschweiften
> Klammer verwenden soll.

So ist es. Es ist eher historischer Ballast von C, dass enum lediglich 
eine Art "int mit benannten Werten" ist. C++ hat den Ballast ablegen 
können, daher ist ein enum dort ein strikter Datentyp.

von A. S. (Gast)


Lesenswert?

Du kannst dir auch von lint checken lassen, ob Du nur enthaltene enums 
verwendest. Am Ende willst Du aber meist doch zumindest auch damit 
indizieren.

Beitrag #5997690 wurde von einem Moderator gelöscht.
von enum (Gast)


Lesenswert?

Alexander schrieb:
> Folgende Linie Codeenum Company Comp4 = test;widerspricht dem
> eigentlichen Sinn der Benutzung von enums (unter
> Berücksichtigung meines restlichen Programms).

Das kann schon Sinn ergeben. Beispiel:
1
enum direction { north, east, south, west };
2
3
...
4
5
for(enum direction dir = north; dir != west; dir++)
6
switch(dir)
7
{
8
case north:
9
break;
10
...
11
}

Zu beachten ist hier das "dir++", das geht nur, weil ein enum sich wie 
ein Integer verhält.

Auch bei der Implementierung von State Machines kann man sowas manchmal 
brauchen. Es ist ein klassischer Fall von: Wenige Leute brauchen es, 
aber es bietet Anfängern relativ viel Gefahrenpotential.

von (prx) A. K. (prx)


Lesenswert?

Dennis Ritchie: `I added some things under some pressure from users that 
I don't think were done well. Enumeration types are a bit odd, bitfields 
are odder. The "static" keyword is very strange, expressing both a 
storage lifetime and what the standard calls "linkage" (external 
visibility). There are many odd bits here and there.´

Beitrag #5997719 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.