51

C/C++ で define ステートメントと enum ステートメントを使用する場合の違いは何ですか (C または C++ で使用する場合に違いはありますか)?

たとえば、いつ使用する必要がありますか

enum {BUFFER = 1234}; 

以上

#define BUFFER 1234   
4

18 に答える 18

65

enum構文要素を定義します。

#defineはプリプリプロセッサディレクティブであり、コンパイラがコードを認識するに実行されるため、C自体の言語要素ではありません。

一般に、列挙型はタイプセーフであり、より簡単に検出できるため、推奨されます。定義は見つけるのが難しく、複雑な動作をする可能性があります。たとえば、あるコードが別のコードで#define作成されたものを再定義できます。これを追跡するのは難しい場合があります。

于 2008-09-25T23:48:21.483 に答える
18

#defineステートメントは、コンパイラがコードを確認する前にプリプロセッサによって処理されるため、基本的にはテキスト置換です(実際には、パラメータなどを使用すると少しインテリジェントになります)。

列挙型はC言語自体の一部であり、次の利点があります。

1 /それらは型を持っている可能性があり、コンパイラはそれらを型チェックできます。

2 /コンパイラーが使用できるため、それらのシンボル情報をデバッガーに渡すことができ、デバッグが容易になります。

于 2008-09-25T23:58:00.137 に答える
8

Defineはプリプロセッサコマンドであり、エディタで「すべて置換」を実行するのと同じように、文字列を別の文字列に置き換えてから結果をコンパイルできます。

列挙型はタイプの特殊なケースです。たとえば、次のように記述します。

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

ERROR_TYPESと呼ばれる新しいタイプが存在します。REGULAR_ERRが1になるのは事実ですが、この型からintにキャストすると、キャスト警告が生成されます(コンパイラーを高冗長性に構成した場合)。

要約:どちらも似ていますが、列挙型を使用すると型チェックが得られ、定義を使用することでコード文字列を置き換えるだけです。

于 2008-09-25T23:53:15.857 に答える
6

列挙型を使用する意味がある場合は、通常、#defineよりも列挙型が優先されます。

  • enumデバッガーは、 s値のシンボリック名を表示できます(「 openType: OpenExisting」ではなく「openType: 2
  • 名前の衝突からもう少し保護されますが、これは以前ほど悪くはありません(ほとんどのコンパイラは#defineリビジョンについて警告します。

最大の違いは、列挙型をタイプとして使用できることです。

// Yeah, dumb example
enum OpenType {
    OpenExisting,
    OpenOrCreate,
    Truncate
};

void OpenFile(const char* filename, OpenType openType, int bufferSize);

これにより、パラメーターの型チェックが可能になり(openTypeとbufferSizeを簡単に混同することはできません)、有効な値を簡単に見つけることができるため、インターフェイスがはるかに使いやすくなります。一部のIDEは、イン​​テリセンスコード補完を提供することもできます。

于 2008-09-26T00:26:40.677 に答える
4

enumは、複数の要素を1つのカテゴリにグループ化できます。

enum fruits{ apple=1234, orange=12345};

#defineは無関係な定数しか作成できませんが:

#define apple 1234
#define orange 12345
于 2010-06-14T07:34:02.987 に答える
4

可能であれば、常に列挙型を使用することをお勧めします。enum を使用すると、ソース コードに関するより多くの情報がコンパイラに提供されます。

たとえば一連のモードを実装する場合、列挙型を使用すると、caseたとえば、スイッチで不足しているステートメントをコンパイラがキャッチできるようになります。

于 2010-06-14T07:28:26.213 に答える
3

#define はプリプロセッサ コマンドで、enum は C または C++ 言語です。

この種のケースでは、#define よりも列挙型を使用することをお勧めします。1 つのことは型の安全性です。もう1つは、値のシーケンスがある場合、列挙型でシーケンスの先頭を指定するだけでよく、他の値は連続した値を取得することです。

enum {
  ONE = 1,
  TWO,
  THREE,
  FOUR
};

それ以外の

#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4

補足として、#define を使用しなければならない場合がまだいくつかあります (通常、定数を含む識別子を作成できるようにする必要がある場合、ある種のマクロの場合)、それはマクロの黒魔術のようなものです。 、そして行く道になることは非常にまれです。これらの極限に行く場合は、おそらく C++ テンプレートを使用する必要があります (ただし、C にこだわっている場合は...)。

于 2010-06-14T07:38:51.803 に答える
2

この単一の定数(たとえばbuffersize)のみが必要な場合は、列挙型ではなく定義を使用します。戻り値(さまざまなエラー条件を意味する)など、さまざまな「タイプ」または「ケース」を区別する必要がある場合は、列挙型を使用します。その場合、列挙型を使用して、関数プロトタイプなどで使用できる新しい型を作成できます。そうすれば、コンパイラーはそのコードの健全性チェックをより適切に行うことができます。

于 2010-06-14T07:31:38.870 に答える
2

すでに書かれているすべてのことのほかに、1つは言ったが示されておらず、代わりに興味深いものです。例えば

enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP };
//...
void do_action( enum action anAction, info_t x );

アクションをタイプとして考えると、物事がより明確になります。define を使用すると、

void do_action(int anAction, info_t x);
于 2010-06-14T07:42:55.930 に答える
2

整数定数値については、よりも好むようになりましenum#define。使用することには欠点がないように見えますがenum(もう少し入力することのわずかな欠点を割り引いて)、enumスコープを設定できるという利点がありますが、#define識別子にはすべてを踏みにじるグローバルスコープがあります。

通常は使用#defineに問題はありませんが、 に欠点がないため、使用enumします。

C++ では、C に移植可能であるため (C とは異なり) 、C++ では aをリテラル整数値の代わりに使用できますが(私はまだ多くの作業を行っています)、一般的に好んenumで使用します。const intconst intenum

于 2010-06-14T07:53:50.817 に答える
1

定数のグループ(「曜日」など)がある場合は、列挙型がグループ化されていることを示しているため、列挙型が適しています。そして、ジェイソンが言ったように、それらはタイプセーフです。それがグローバル定数(バージョン番号など)の場合、それはあなたが使用するものです#define。これは多くの議論の対象ですが。

于 2008-09-25T23:54:04.187 に答える
1

列挙型は、週の日など、ある種のセットを列挙するために使用されます。定数が1つだけ必要な場合const int(またはdoubleなど)は、enumよりも明らかに優れています。私は個人的には好きではありません#define(少なくともいくつかの定数の定義についてはそうではありません)。型の安全性が得られないからです。

于 2010-06-14T07:30:08.013 に答える
1

上記の良い点に加えて、列挙型のスコープをクラス、構造体、または名前空間に制限できます。個人的には、一度にスコープ内の関連シンボルの数を最小限に抑えるのが好きです。これは、#defines ではなく列挙型を使用するもう 1 つの理由です。

于 2008-09-26T10:37:15.107 に答える
1

定義のリストに対する列挙型のもう 1 つの利点は、switch ステートメントですべての値がチェックされていない場合に、コンパイラ (少なくとも gcc) が警告を生成できることです。例えば:

enum {
    STATE_ONE,
    STATE_TWO,
    STATE_THREE
};

...

switch (state) {
case STATE_ONE:
    handle_state_one();
    break;
case STATE_TWO:
    handle_state_two();
    break;
};

前のコードでは、コンパイラは列挙型のすべての値がスイッチで処理されないという警告を生成できます。状態が #define として実行された場合、これは当てはまりません。

于 2008-09-29T01:32:22.510 に答える
1

列挙型を作成すると、リテラルだけでなく、これらのリテラルをグループ化する型も作成されます。これにより、コンパイラがチェックできるコードにセマンティックが追加されます。

さらに、デバッガーを使用すると、列挙型リテラルの値にアクセスできます。これは、#define では必ずしも当てはまりません。

于 2010-06-14T08:13:50.890 に答える