C/C++ で define ステートメントと enum ステートメントを使用する場合の違いは何ですか (C または C++ で使用する場合に違いはありますか)?
たとえば、いつ使用する必要がありますか
enum {BUFFER = 1234};
以上
#define BUFFER 1234
C/C++ で define ステートメントと enum ステートメントを使用する場合の違いは何ですか (C または C++ で使用する場合に違いはありますか)?
たとえば、いつ使用する必要がありますか
enum {BUFFER = 1234};
以上
#define BUFFER 1234
enum
構文要素を定義します。
#define
はプリプリプロセッサディレクティブであり、コンパイラがコードを認識する前に実行されるため、C自体の言語要素ではありません。
一般に、列挙型はタイプセーフであり、より簡単に検出できるため、推奨されます。定義は見つけるのが難しく、複雑な動作をする可能性があります。たとえば、あるコードが別のコードで#define
作成されたものを再定義できます。これを追跡するのは難しい場合があります。
#define
ステートメントは、コンパイラがコードを確認する前にプリプロセッサによって処理されるため、基本的にはテキスト置換です(実際には、パラメータなどを使用すると少しインテリジェントになります)。
列挙型はC言語自体の一部であり、次の利点があります。
1 /それらは型を持っている可能性があり、コンパイラはそれらを型チェックできます。
2 /コンパイラーが使用できるため、それらのシンボル情報をデバッガーに渡すことができ、デバッグが容易になります。
Defineはプリプロセッサコマンドであり、エディタで「すべて置換」を実行するのと同じように、文字列を別の文字列に置き換えてから結果をコンパイルできます。
列挙型はタイプの特殊なケースです。たとえば、次のように記述します。
enum ERROR_TYPES
{
REGULAR_ERR =1,
OK =0
}
ERROR_TYPESと呼ばれる新しいタイプが存在します。REGULAR_ERRが1になるのは事実ですが、この型からintにキャストすると、キャスト警告が生成されます(コンパイラーを高冗長性に構成した場合)。
要約:どちらも似ていますが、列挙型を使用すると型チェックが得られ、定義を使用することでコード文字列を置き換えるだけです。
列挙型を使用する意味がある場合は、通常、#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は、インテリセンスコード補完を提供することもできます。
enumは、複数の要素を1つのカテゴリにグループ化できます。
enum fruits{ apple=1234, orange=12345};
#defineは無関係な定数しか作成できませんが:
#define apple 1234
#define orange 12345
可能であれば、常に列挙型を使用することをお勧めします。enum を使用すると、ソース コードに関するより多くの情報がコンパイラに提供されます。
たとえば一連のモードを実装する場合、列挙型を使用すると、case
たとえば、スイッチで不足しているステートメントをコンパイラがキャッチできるようになります。
#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 にこだわっている場合は...)。
この単一の定数(たとえばbuffersize)のみが必要な場合は、列挙型ではなく定義を使用します。戻り値(さまざまなエラー条件を意味する)など、さまざまな「タイプ」または「ケース」を区別する必要がある場合は、列挙型を使用します。その場合、列挙型を使用して、関数プロトタイプなどで使用できる新しい型を作成できます。そうすれば、コンパイラーはそのコードの健全性チェックをより適切に行うことができます。
すでに書かれているすべてのことのほかに、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);
整数定数値については、よりも好むようになりましenum
た#define
。使用することには欠点がないように見えますがenum
(もう少し入力することのわずかな欠点を割り引いて)、enum
スコープを設定できるという利点がありますが、#define
識別子にはすべてを踏みにじるグローバルスコープがあります。
通常は使用#define
に問題はありませんが、 に欠点がないため、使用enum
します。
C++ では、C に移植可能であるため (C とは異なり) 、C++ では aをリテラル整数値の代わりに使用できますが(私はまだ多くの作業を行っています)、一般的に好んenum
で使用します。const int
const int
enum
定数のグループ(「曜日」など)がある場合は、列挙型がグループ化されていることを示しているため、列挙型が適しています。そして、ジェイソンが言ったように、それらはタイプセーフです。それがグローバル定数(バージョン番号など)の場合、それはあなたが使用するものです#define
。これは多くの議論の対象ですが。
列挙型は、週の日など、ある種のセットを列挙するために使用されます。定数が1つだけ必要な場合const int
(またはdoubleなど)は、enumよりも明らかに優れています。私は個人的には好きではありません#define
(少なくともいくつかの定数の定義についてはそうではありません)。型の安全性が得られないからです。
上記の良い点に加えて、列挙型のスコープをクラス、構造体、または名前空間に制限できます。個人的には、一度にスコープ内の関連シンボルの数を最小限に抑えるのが好きです。これは、#defines ではなく列挙型を使用するもう 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 として実行された場合、これは当てはまりません。
列挙型を作成すると、リテラルだけでなく、これらのリテラルをグループ化する型も作成されます。これにより、コンパイラがチェックできるコードにセマンティックが追加されます。
さらに、デバッガーを使用すると、列挙型リテラルの値にアクセスできます。これは、#define では必ずしも当てはまりません。