Cの列挙型を使用するための適切な構文が何であるかわかりません。次のようなコードがあります。
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
しかし、これはコンパイルされず、次のエラーが表示されます。
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
何がおかしいのですか?
列挙型変数を宣言するには、次のようにします。
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;
しかし、変数宣言を短くするためにtypedef
を使うことができます。
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;
型と変数を区別するための命名規則を持つことは良い考えです。
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
それはあなたがneedtypedef
ではないことを指摘する価値があります。次のようにしてください。
enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;
あなたがtypedef
を好むかどうかはスタイルの問題です。それがなければ、列挙型を参照したい場合はenum strategy
を使用する必要があります。それで、あなたはstrategy
と言うことができます。
どちらの方法にも長所と短所があります。 1つは、より言葉遣いですが、通常の識別子と衝突しないように型識別子をtag-namespaceに保持し(struct stat
とstat
関数についても考えてください:これらは衝突しません)、すぐに型であることがわかります。もう1つは短いですが、型識別子を通常の名前空間に取り入れます。
あなたはstrategy
を2回宣言しようとしています、そしてそれはあなたが上記のエラーを得ている理由です。以下は(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;
}
上記の代わりに、2行目が次のように変更されました。
...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...
警告から、あなたは簡単にあなたの間違いを見ることができます:
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
そのため、デフォルトの型がstrategy
であるint
という名前の変数の宣言にコンパイラがstrategy = IMMEDIATE
を使用しましたが、この名前の変数の以前の宣言はすでにありました。
ただし、main()
関数に代入した場合、それは有効なコードになります。
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
strategy=SEARCH;
printf("strategy: %d\n", strategy);
return 0;
}
あなたが言う時
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
名前のないenumの 'strategy'と呼ばれる単一のインスタンス変数を作成します。これはそれほど便利なことではありません - typedefが必要です。
typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType;
StrategyType strategy = IMMEDIATE;
書かれているように、あなたのコードに問題はありません。こんなことをしていないのですか?
int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
エラーメッセージはどの行を指していますか? 「以前の '戦略'の宣言はここにありました」と言ったとき、何がここにあり、それは何を表していますか?
投稿された質問へのコメントの@ThoAppelsinは正しいです。コードスニペットは、それが有効で、エラーなしで質問に投稿しました。あなたが持っているエラーはあなたのCソースファイルの他の場所の他の悪い構文によるものでなければなりません。 enum{a,b,c};
は、それぞれ0
、1
および2
の値を持つ整数である3つのシンボリック定数(a
、b
およびc
)を定義しますが、enum
を使用する場合、通常は特定の整数値を気にしないのでシンボリック定数名これはあなたがこれを持つことができることを意味します:
#include <stdio.h>
enum {a,b,c};
int main(){
printf("%d\n",b);
return 0;
}
そしてこれは1
を出力します。
これも有効になります。
#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
printf("%d\n",bb);
return 0;
}
以前と同じように出力されます。
あなたがこれをするならば:
enum {a,b,c};
enum {a,b,c};
あなたはエラーがあるでしょう、しかしあなたがこれをするなら:
enum alfa{a,b,c};
enum alfa;
あなたはエラーがないでしょう。
あなたはこれを行うことができます:
enum {a,b,c};
int aa=a;
そしてaa
は値0
を持つ整数変数になります。しかし、あなたもこれを行うことができます:
enum {a,b,c} aa= a;
同じ効果があります(つまり、aa
は0
値を持つint
です)。
あなたもこれを行うことができます:
enum {a,b,c} aa= a;
aa= 7;
そしてaa
は値7
を持つint
になります。
前述したように、enum
を使用して記号定数定義を繰り返すことはできないため、int
を使用してenum
varsを宣言する場合は、タグを使用する必要があります。
enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;
typedef
を使用すると、毎回enum tag1
を記述して変数を定義するのを防ぐことができます。 typedef
では、Tag1
と入力するだけです。
typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;
あなたも持つことができます:
typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;
最後に言うべきことは、定義済みの記号定数について話しているので、enum
を使うときは大文字を使うのが良いということです。例えば:
enum {A,B,C};
の代わりに
enum {a,b,c};
C++でtypedefステートメントを必要とせずに "enum"を使用して新しいタイプを定義できることを言及する価値があります。
enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;
私はこのアプローチがはるかに友好的であると思います。
[編集 - C++の状態を明確に - 私はもともとこれを持っていたが、それを削除した!]
宣言について混乱があるようです。
次のようにstrategy
が{RANDOM, IMMEDIATE, SEARCH}
より前になると、
enum strategy {RANDOM, IMMEDIATE, SEARCH};
あなたはenum strategy
という名前の新しい型を作成しています。ただし、変数を宣言するときは、enum strategy
自体を使用する必要があります。 strategy
だけを使用することはできません。したがって、以下は無効です。
enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;
その間、以下は有効です
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];
strategy
が{RANDOM, IMMEDIATE, SEARCH}
の後に来るとき、あなたは匿名のenumを作成して、それからその型の変数であるとstrategy
を宣言しています。
だから今、あなたはのような何かをすることができます
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;
ただし、名前を付けたことがないため、enum {RANDOM, IMMEDIATE, SEARCH}
型の他の変数を宣言することはできません。だから以下は無効です
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;
両方の定義を組み合わせることもできます
enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;
a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;
前述のようにTypedef
は、短い変数宣言を作成するために使用されます。
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum {RANDOM, IMMEDIATE, SEARCH}
はstrategy
と同義語であることをコンパイラに伝えました。それで今あなたは変数型として自由にstrategy
を使うことができます。もうenum strategy
を入力する必要はありません。以下が有効になりました
strategy x = RANDOM;
Typedefと列挙型の名前を組み合わせて取得することもできます。
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy
とenum strategyName
を互換的に使用できるようになったという事実を除けば、このメソッドを使用する利点はそれほどありません。
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategyName a = RANDOM;
strategy b = SEARCH;
列挙の名前を宣言してもエラーは発生しません。
宣言されていない場合は、typedef
を使用する必要があります。
enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
エラーは表示されません。
私のお気に入りで唯一の中古建築はいつもでした:
typedef enum MyBestEnum
{
/* good enough */
GOOD = 0,
/* even better */
BETTER,
/* divine */
BEST
};
私はこれがあなたが抱えている問題を取り除くと信じています。新しいタイプを使用することは私の観点から正しい選択です。
Tarcの答えは最高です。
列挙型ディスカッションの大部分は、赤いニシンです。
このコードスニペットを比較してください -
int strategy;
strategy = 1;
void some_function(void)
{
}
これは
error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition
これで問題なくコンパイルできます。
int strategy;
void some_function(void)
{
strategy = 1;
}
変数strategy
は、宣言時や関数内などで設定する必要があります。グローバルスコープで、任意のソフトウェア、特に割り当てを書くことはできません。
彼がintの代わりにenum {RANDOM、IMMEDIATE、SEARCH}を使用したという事実は、それを超えて見ることができない人々を混乱させているという意味においてのみ関連性があります。質問の中の再定義エラーメッセージは、これが著者が間違ったことであることを示しています。
それで、今あなたは以下の例の最初が間違っていて、他の3つが大丈夫である理由を見ることができるはずです。
例1間違っている
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void)
{
}
例2正しいです。
enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void)
{
}
例3正しいです。
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void)
{
strategy = IMMEDIATE;
}
例4正しいです。
void some_function(void)
{
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
}
もしあなたが実用的なプログラムを持っているならば、あなたは単にあなたのプログラムにこれらの断片を貼り付けることができるべきであり、そしてあるものはコンパイルしそしてあるものはそうしないことを見るべきです。
私はgccを試してみましたが、エラーなしでコンパイルするために、最後の選択肢を使わざるを得なかったので、私の必要性を思いつきました。
typedef enumstate{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);