it-swarm.com.de

Wie definiere ich einen Aufzählungstyp (enum) in C?

Ich bin mir nicht sicher, was die richtige Syntax für die Verwendung von C-Enums ist. Ich habe folgenden Code:

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

Dies wird jedoch nicht mit dem folgenden Fehler kompiliert:

error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here

Was mache ich falsch?

253
lindelof

Das Deklarieren einer Enumevariable geschieht folgendermaßen:

enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;

Sie können jedoch eine typedef verwenden, um die Variablendeklarationen wie folgt zu verkürzen:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;

Eine Namenskonvention zur Unterscheidung zwischen Typen und Variablen ist eine gute Idee:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
358
RichieHindle

Es lohnt sich, darauf hinzuweisen, dass Sie brauchen eine typedef nicht. Sie können es einfach wie folgt machen

enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;

Es ist eine Stilfrage, ob Sie typedef bevorzugen. Wenn Sie sich nicht auf den Aufzählungstyp beziehen möchten, müssen Sie enum strategy verwenden. Damit können Sie einfach strategy sagen.

Beide Möglichkeiten haben ihre Vor- und Nachteile. Die eine ist wortreicher, hält aber Typbezeichner im Tag-Namespace, wo sie keinen Konflikt mit gewöhnlichen Bezeichnern haben (denken Sie an struct stat und die stat-Funktion: diese stehen auch nicht in Konflikt) und Sie sehen sofort, dass es sich um einen Typ handelt . Die andere ist kürzer, bringt jedoch Typbezeichner in den gewöhnlichen Namespace. 

441

Sie versuchen zweimal, strategy zu deklarieren, und deshalb erhalten Sie den obigen Fehler. Folgendes funktioniert ohne Beanstandungen (zusammengestellt mit gcc -ansi -pendantic -Wall):

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    printf("strategy: %d\n", strategy);

    return 0;
}

Wenn statt der obigen die zweite Zeile geändert wurde:

...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...

An den Warnungen können Sie Ihren Fehler leicht erkennen:

enums.c:5:1: warning: data definition has no type or storage class [enabled by default]
enums.c:5:1: warning: type defaults to ‘int’ in declaration of ‘strategy’ [-Wimplicit-int]
enums.c:5:1: error: conflicting types for ‘strategy’
enums.c:4:36: note: previous declaration of ‘strategy’ was here

Der Compiler nahm strategy = IMMEDIATE für die Deklaration einer Variablen mit dem Namen strategy mit dem Standardtyp int an, aber bereits eine Deklaration einer Variablen mit diesem Namen war vorhanden.

Wenn Sie die Zuweisung in die Funktion main() einfügen, wäre dies ein gültiger Code:

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    strategy=SEARCH;
    printf("strategy: %d\n", strategy);

    return 0;
}
53
Tarc

Wenn du sagst

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

sie erstellen eine einzelne Instanzvariable namens "Strategie" einer namenlosen Enumeration. Dies ist nicht sehr nützlich - Sie benötigen ein Typedef:

typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType; 
StrategyType strategy = IMMEDIATE;
47
anon

Wie geschrieben, ist mit Ihrem Code nichts falsch. Bist du sicher, dass du so etwas nicht getan hast?

int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Auf welche Zeilen verweisen die Fehlermeldungen? Wenn dort steht, dass "vorherige Erklärung von" Strategie hier war ", was ist hier" und was zeigt es? 

13
John Bode

@ThoAppelsin hat in seinem Kommentar zu der geposteten Frage Recht. Das in der Frage angegebene Code-Snippet ist gültig und fehlerfrei. Der Fehler, den Sie haben, muss an einer anderen Stelle in Ihrer c-Quelldatei liegen, weil die Syntax fehlerhaft ist. enum{a,b,c}; definiert drei symbolische Konstanten (a, b und c), bei denen es sich um Ganzzahlen mit Werten 0, 1 und 2 handelt. Wenn wir jedoch enum verwenden, kümmern wir uns in der Regel um die Bedeutung der Ganzzahl des symbolischen konstanten Namens. Dies bedeutet, dass Sie Folgendes haben können:

#include <stdio.h>
enum {a,b,c};
int main(){
  printf("%d\n",b);
  return 0;
}

und dies gibt 1 aus.

Dies gilt auch:

#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
  printf("%d\n",bb);
  return 0;
}

und wird wie zuvor ausgegeben.

Wenn du das tust:

enum {a,b,c};
enum {a,b,c};

sie werden einen Fehler haben, aber wenn Sie dies tun:

enum alfa{a,b,c};
enum alfa;

sie werden keinen Fehler haben.

du kannst das:

enum {a,b,c};
int aa=a;

und aa ist eine Ganzzahlvariable mit dem Wert 0. Sie können dies aber auch tun:

enum {a,b,c} aa= a;

und hat den gleichen Effekt (dh aa ist ein int mit 0-Wert). 

sie können das auch tun:

enum {a,b,c} aa= a;
aa= 7;

und aa wird int mit dem Wert 7 sein.

da Sie die symbolische Konstantendefinition mit der Verwendung von enum nicht wiederholen können, müssen Sie, wie bereits gesagt, Tags verwenden, wenn Sie int vars mit der Verwendung von enum deklarieren möchten:

enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;

durch die Verwendung von typedef müssen Sie jedes Mal enum tag1 schreiben, um eine Variable zu definieren. Mit typedef können Sie einfach Tag1 eingeben:

typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;

Sie können auch haben:

typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;

Das letzte, was zu sagen ist, ist, da wir über definierte symbolische Konstanten sprechen, ist es besser, Großbuchstaben zu verwenden, wenn enum verwendet wird. Dies ist zum Beispiel:

enum {A,B,C};

anstatt 

enum {a,b,c};
11
roggc

Es ist erwähnenswert, dass in C++ "enum" verwendet werden kann, um einen neuen Typ zu definieren, ohne eine Typedef-Anweisung zu benötigen. 

enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;

Ich finde diesen Ansatz viel freundlicher.

[Bearbeiten - geklärter C++ - Status - Ich hatte dies ursprünglich in, dann entfernte es!]

10
Roddy

Es scheint eine Verwirrung über die Erklärung zu geben.

Wenn strategy vor {RANDOM, IMMEDIATE, SEARCH} wie im Folgenden vorkommt,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

sie erstellen einen neuen Typ mit dem Namen enum strategy. Bei der Deklaration der Variablen müssen Sie jedoch enum strategy selbst verwenden. Sie können nicht einfach strategy verwenden. Das Folgende ist also ungültig.

enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;

Währenddessen gilt Folgendes

enum strategy {RANDOM, IMMEDIATE, SEARCH};

enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];

Wenn strategy nach {RANDOM, IMMEDIATE, SEARCH} kommt, erstellen Sie ein anonymes Enum und deklarieren dann strategy als Variable dieses Typs.

So, jetzt kannst du so etwas machen

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;

Sie können jedoch keine andere Variable vom Typ enum {RANDOM, IMMEDIATE, SEARCH} deklarieren, da Sie sie nie benannt haben. Das Folgende ist also ungültig

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;

Sie können beide Definitionen auch kombinieren

enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;

a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;

Typedef wird, wie bereits erwähnt, zum Erstellen einer kürzeren Variablendeklaration verwendet.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Nun haben Sie dem Compiler mitgeteilt, dass enum {RANDOM, IMMEDIATE, SEARCH} mit strategy übereinstimmt. Nun können Sie strategy als Variablentyp frei verwenden. Sie müssen nicht mehr enum strategy eingeben. Das Folgende ist jetzt gültig

strategy x = RANDOM;

Sie können auch Typedef mit dem Namen der Enumeration kombinieren

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

Die Verwendung dieser Methode bietet nur einen geringen Vorteil, außer dass Sie jetzt strategy und enum strategyName austauschbar verwenden können.

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

enum strategyName a = RANDOM;
strategy b = SEARCH;
6
Confuse

Wenn Sie den Namen für die Aufzählung angeben, tritt kein Fehler auf.

Wenn nicht deklariert, müssen Sie eine typedef verwenden:

enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

Es wird kein Fehler angezeigt ...

2
user3135028

Meine Lieblings- und einzige gebrauchte Konstruktion war immer:

typedef enum MyBestEnum
{
    /* good enough */
    GOOD = 0,
    /* even better */
    BETTER,
    /* divine */
    BEST
};

Ich glaube, dass dies Ihr Problem beseitigen wird. Die Verwendung eines neuen Typs ist aus meiner Sicht die richtige Option.

1
Sany

Tarcs Antwort ist das Beste.

Ein Großteil der Diskussionsrunde ist ein roter Hering.

Vergleichen Sie dieses Code-Snippet: -

int strategy;
strategy = 1;   
void some_function(void) 
{
}

was gibt 

error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition

mit diesem, das ohne problem kompiliert.

int strategy;
void some_function(void) 
{
    strategy = 1;   
}

Die Variable strategy muss bei der Deklaration oder innerhalb einer Funktion usw. gesetzt werden. Sie können keine beliebige Software - insbesondere Zuweisungen - im globalen Gültigkeitsbereich schreiben.

Die Tatsache, dass er die Aufzählung {RANDOM, IMMEDIATE, SEARCH} anstelle von int verwendet hat, ist nur insofern relevant, als er Menschen verwirrt hat, die nicht darüber hinaus sehen können der autor hat falsch gemacht.

Nun sollten Sie in der Lage sein zu erkennen, warum das erste der folgenden Beispiele falsch ist und die anderen drei in Ordnung sind.

Beispiel 1. FALSCH!

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void) 
{
}

Beispiel 2. RECHTS.

enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void) 
{
}

Beispiel 3. RECHTS.

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void) 
{
    strategy = IMMEDIATE;
}

Beispiel 4. RECHTS.

void some_function(void) 
{
    enum {RANDOM, IMMEDIATE, SEARCH} strategy;
    strategy = IMMEDIATE;
}

Wenn Sie ein funktionierendes Programm haben, sollten Sie diese Ausschnitte einfach in Ihr Programm einfügen können und sehen, dass einige kompilieren und andere nicht.

1
user3070485

Ich habe es mit gcc ausprobiert und kam zu dem Schluss, dass ich gezwungen war, die letzte Alternative zu verwenden, um ohne Fehler zu kompilieren. 

typedef enum state {a = 0, b = 1, c = 2} state ;

typedef enum state {a = 0, b = 1, c = 2} state;

typedef enum state old; // New type, alias of the state type.
typedef enum state new; // New type, alias of the state type.

new now     = a;
old before  = b;

printf("State   now = %d \n", now);
printf("Sate before = %d \n\n", before);
0
gg cg