2016-03-18 6 views
2

In C, auch der folgende Code gibt einen Fehler (wegen orange):Können enums durch c in C ersetzt werden?

enum color {yellow, blue, green, red, brown, black, white, purple, orange}; 
enum fruit {cherry, apple, pear, melon, banana, strawberry, raspberry, orange}; 

Aber Code wie folgt:

enum fruit {cherry = 1, apple = 2, pear = 3, melon = 4, banana = 5, strawberry = 6, raspberry = 7, orange = 8}; 

int main(int argc, char *argv[]){ 
    enum fruit f; 
    int x; 

    x = apple; 
    f = -7; 

    return 0; 
} 

Kompiliert mit gcc --std=c89 -pedantic.

Es scheint enum s kann leicht durch const Variablen ersetzt:

typedef int fruit; 
const fruit cherry = 1, apple = 2, pear = 3, melon = 4, banana = 5, strawberry = 6, raspberry = 7, orange = 8; 

int main(int argc, char *argv[]){ 
    fruit f; 
    int x; 

    x = apple; 
    f = -7; 

    return 0; 
} 

Die nur Weg enum anders verhält isthat können Sie absolut nicht den Wert von cherry, apple, ... ändern, während bei der Verwendung von const s man könnte versuchen, die üblichen Tricks wie int *y = &apple; *y = -7; (mit gcc Ich bekomme eine Warnung, aber es kompiliert).

Ist das der einzige Unterschied oder habe ich etwas verpasst?

+1

'const Obst Apfel = 1; int * y = &apple; * y = -7; '. Undefiniertes Verhalten erhalten Sie, wenn Sie eine 'const'-Variable modifizieren. ** Edit **: Scheinbar wird es eher eine "Constraint-Verletzung" genannt, und eine C-Implementierung ist erforderlich, um davor zu warnen. – 3442

+0

Worum geht es, wenn Sie es "const" deklarieren, wenn Sie es ändern wollen? – axiac

+0

Eine bessere Frage wäre, warum 'const' benötigt wird, wenn man' enum' Konstanten verwenden kann (die garantiert so effizienten Maschinencode wie Literalzahlen liefern, während bei 'const' Werten dies von Optimierungen abhängt). – hyde

Antwort

4

Es gibt mehrere signifikante Unterschiede zwischen enum Konstanten und const -qualifizierten Objekten.

Eine enum Typdeklaration wie

enum fruit {cherry, apple, pear}; 

automatisch sequentielle Werte zuordnet mit 0 zu den Konstanten Ausgangs cherry, apple und pear. (Sie können diese Werte bei Bedarf überschreiben.) Das bedeutet, dass (a) Sie die Konstanten beliebig anordnen können und der Compiler sich um die Werte kümmert und (b) das Risiko, versehentlich falsche Werte zu verwenden, geringer ist.

Eine Alternative wie:

const int cherry = 0; 
const int apple = 1; 
const int pear = 2; 

schwieriger zu halten - und, was vielleicht am wichtigsten ist, die Namen cherry et al sind nicht konstant Ausdrücke. Das bedeutet zum Beispiel, dass Sie sie nicht in Fallbezeichnungen oder in anderen Kontexten verwenden können, die einen konstanten Ausdruck erfordern.

Um den Wert eines const -qualifizierten Objekts zu ändern, ist dies direkt eine Constraint-Verletzung, die eine Kompilierungszeitdiagnose erfordert. (gcc neigt dazu, standardmäßig solche Diagnose-Warnungen zu erstellen, die nicht tödlich sind.) Sie können versuchen, es indirekt zu ändern, z. B. mit einem Zeiger-Cast, aber mit einem nicht definierten Verhalten.

Eine Sache, über C der enum Arten zu erinnern ist, dass die Konstanten sind vom Typ int, nicht des Aufzählungstypen. Normalerweise spielt dies keine Rolle, da der Wert in den meisten Kontexten implizit in den richtigen Typ konvertiert wird. (C++ hat andere Regeln, aber die Frage ist, C.)

0

enum wird in der Regel als logische Variablen verwendet, wie Sie in Ihrem Beispiel erwähnt, wie color und fruit, wo man wirklich nicht über die tatsächlichen numerischen Wert Pflege von jedes Element, sondern auf was es darstellt.

const auf der anderen Seite, wird normalerweise verwendet, wenn Sie tatsächlich über den numerischen Wert kümmern. Zum Beispiel:

const float PI = 3.1415926; 

So wie für Ihre Frage, die Antwort ist ja, Enum durch const Werte ersetzt werden kann, aber die Frage ist, ob es eine wahre dafür Use-Case ist