Forum: Compiler & IDEs Frage zu C Syntax (set von enums)


von Michael L. (fliegermichl)


Lesenswert?

Hallo zusammen,

ich programmiere normalerweise in Pascal. Man kann da sog. Sets 
definieren.
1
type
2
 TRunMode = (rmNone, rmStart, rmPreRun, rmRun, rmPostRun);
3
4
var RunMode : TRunMode;
5
6
type TRunModeSet = set of TRunMode;
7
8
var RunModeSet : TRunModeSet;
Die Variable RunMode kann dann jeden der Werte von rmNone bis rmPostRun 
annehmen. Die Variable RunModeSet kann keinen, einen, mehrere oder auch 
alle Werte von TRunMode beinhalten.

Beim Vergleichen kann man dann mit
1
if (RunMode in [rmPreRun, rmRun, rmPostRun]) then
2
 // Machwas
3
else
4
 // Machwasanderes
5
;
prüfen, ob RunMode einen der gefragten Werte beinhaltet.

Kann man soetwas ähnliches auch in C mit enums machen?

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Im Prinzip ja, mit einem switch-case:
1
enum bla
2
{
3
  zwiebel,
4
  gurke,
5
  paprika,
6
  kartoffel
7
};
8
9
10
enum bla x;
11
12
switch (x)
13
{
14
  case zwiebel:
15
  case gurke:
16
  case kartoffel:
17
    machwas();
18
    break;
19
20
  default:
21
    machwasanderes();
22
    break;
23
}

Man kann aber --außer mit nichtportablen Spracherweiterungen mancher 
Compiler-- bei dieser Syntax keine Wertebereiche angeben (also "zwiebel 
bis paprika").

: Bearbeitet durch User
von Michael L. (fliegermichl)


Lesenswert?

Danke für die schnelle Antwort,

in einer if Bedingung muß ich dann also mit
1
if (x == Gurke || x == Kartoffel) ...
arbeiten.

Ich wusste doch weshalb ich lieber in Pascal programmiere :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Michael Läßig schrieb:
> in einer if Bedingung muß ich dann also mitif (x == Gurke || x ==
> Kartoffel) ...
> arbeiten.

Nicht zwingend.

Wenn die Anzahl der enum-Konstanten nicht größer als die Anzahl der Bits 
im verwendeten Datentyp ist, kann man das auch so lösen:
1
enum bla
2
{
3
  zwiebel = 1,
4
  gurke = 2,
5
  paprika = 4,
6
  kartoffel = 8
7
};
8
9
10
enum bla x;
11
12
if (x & (zwiebel | gurke))
13
  machwas();
14
else
15
  machwasanderes();

von Haro (Gast)


Lesenswert?

Sowas geht, find ich aber sehr unschön.

enums sollten meiner Meinung nach (und laut Meinung meiner bisherigen 
Arbeitgeber) nur als symbolische Bezeichner herhalten, um den Code 
lesbarer zu machen. Um Zuständen zB Namen anstatt Nummern verpassen zu 
können.
Sobald die Zahl, die durch ein enum-literal repräsentiert wird eine 
Rolle spielt, würd ich auf defines ausweichen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

und wenn deine (und die Meinung deiner bisherigen Arbeitgeber) falsch 
ist?

Preisfrage: Was ist der große große große Unterschied zwischen einem 
enum und einem define?

von Karl H. (kbuchegg)


Lesenswert?

Haro schrieb:

> Sobald die Zahl, die durch ein enum-literal repräsentiert wird eine
> Rolle spielt, würd ich auf defines ausweichen.

Was versprichst du (bzw. dein Arbeitgeber) dir davon?

Meiner Meinung nach, werden enum überschätzt. Das was sie sein sollten, 
sind sie nicht. Dazu ist ihre Definition zu schwach. enum sind nichts 
anderes als Integer, die einen Namen erhalten haben, der sie in den Rang 
eines Pseudodatentyps hievt. Das hat Vorteile in der Dokumentation von 
Funktionsschnittstellen. Das hat auch Vorteile, dass Debugger 
normalerweise mit den Werten gut klar kommen ohne dass ich als 
Programmierer erst mal lang im Code nach dem entsprechenden #define 
suchen muss. Aber 'Datentyp-sicherheitstechnisch' sind enums genau die 
gleiche Katastrophe wie #define.

Für das, was in Pascal Mengen sind, sind enums keine wirklicher Ersatz, 
auch wenn es auf den ersten Blick so aussieht. Die Mengen in Pascal sind 
schön, aber so schön dann auch wieder nicht, das man ohne sie nicht 
auskommen würde. Was nicht heißen soll, dass ich sie für Mumpitz halte - 
nicht falsch verstehen.

: Bearbeitet durch User
von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl Heinz schrieb:
> Aber 'Datentyp-sicherheitstechnisch' sind enums genau die
> gleiche Katastrophe wie #define.

Ähhhh... nein?
1
typedef enum {A, B, C} abc_t;
2
typedef enum {X, Y, Z} xyz_t;
3
4
abc_t abc = A;
5
xyz_t xyz = X;
6
7
if (abc == xyz)  {
8
   printf ("Error\n");
9
}
führt mit gcc -W -Wall (was Standardeinstellung sein sollte) zu

test4.c:12:13: warning: comparison between ‘abc_t’ and ‘xyz_t’ 
[-Wenum-compare]

Wobei ich jetzt nicht ausprobieren mag was noch alles verwarnt wird (und 
was nicht ;-)

von Karl H. (kbuchegg)


Lesenswert?

Michael Reinelt schrieb:

> führt mit gcc -W -Wall (was Standardeinstellung sein sollte) zu
>
> test4.c:12:13: warning: comparison between ‘abc_t’ and ‘xyz_t’
> [-Wenum-compare]

Warnungen sind nicht normativ.

Nichts und niemand in der C-Norm hindert dich an
1
  abc_t abc = A;
2
3
  abc = 8;

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl Heinz schrieb:
> Warnungen sind nicht normativ.
Ja, aber zumindest geb ich dem Compiler eine Chance, zu erkennen was ich 
wollte und was nicht (aber schlussendlich gilt auch hier: Das Programm 
macht was du schreibst, nicht was du willst)

> Nichts und niemand in der C-Norm hindert dich an
>
>
1
>   abc_t abc = A;
2
>   abc = 8;
3
>

Leider richtig. Und nicht mal mit extremen -W's meckert er das an :-(

von B. S. (bestucki)


Lesenswert?

Karl Heinz schrieb:
> Aber 'Datentyp-sicherheitstechnisch' sind enums genau die
> gleiche Katastrophe wie #define.

Da geb ich dir recht. Man muss einfach wissen was man tut und dass ein 
enum dasselbe wie ein int ist. Ich wünsche mir auch, dass ein enum in C 
ein eigenständiger Datentyp ist und nur Werte zulässt, die definiert 
wurden. So könnte man viele Programme viel sicherer schreiben.

Ich verwende enums gerne dort, wo mich der der Wert der Variable nicht 
interessiert, z.B.:
- Zustände einer Zustandsmaschine
- Kennzahl einer union
- Parameter für eine Funktion, die nur einige definierte Werte zulässt 
(Wert wird vor der Verwendung geprüft)

von Haro (Gast)


Lesenswert?

Karl Heinz schrieb:
> Was versprichst du (bzw. dein Arbeitgeber) dir davon?

Es ist einfach eine weitere Konvention.
Sowas wie "Makros groß" halt. Als Programmierer seh ich sofort was da 
los ist. Auf den ersten Blick. Zumindest bei uns halt.

Mal ganz davon abgesehen dass enums je nach Compilerflags 
signed/unsigned oder verschieden breit sein können.
Dadurch könnte irgendeine entartete enum-Aritmethik auf einmal nicht 
mehr funktionieren wie gedacht (mal abgesehn dass sowas hoffentlich 
niemand macht).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Haro schrieb:
> Mal ganz davon abgesehen dass enums je nach Compilerflags
> signed/unsigned oder verschieden breit sein können.

Es ist aber ein grober Schnatzer, entsprechende Flags wie -fshort-enums 
zu setzen, denn das sind keine Optimierungsflags, sondern sie 
verändern das Binärinterface (ABI). Ditto für -f[no]-[un]signed-char 
oder -f[un]signed-bitfields, -fpack-struct o.ä.

Wenn man das ABI äbdert braucht man sich nicht zu wundern, wenn nix mehr 
geht :-)

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.