2008-09-25 89 views

回答

55

enum限定了語法元素。

#define是一個預處理器指令,執行之前編譯器看到的代碼,因此不是C本身的語言元素。

通常枚舉是首選,因爲它們是類型安全的,更容易發現。定義很難找到並且可能有複雜的行爲,例如,一段代碼可以重新定義由另一個代碼生成的#define。這可能很難追查到。

+21

你也可以把枚舉在命名空間,而宏不能。 – 2008-09-26 03:48:50

+0

然而,宏可以更容易地將源代碼本身(例如從構建命令內)的外側配置 – 2016-01-31 17:32:07

8

Define是一個預處理器命令,它就像在你的編輯器中「替換全部」一樣,它可以用另一個替換字符串,然後編譯結果。

枚舉類型是一種特殊情況下,例如,如果你寫:

enum ERROR_TYPES 
{ 
    REGULAR_ERR =1, 
    OK =0 
} 

存在一種新的類型,稱爲ERROR_TYPES。 的確,REGULAR_ERR的結果爲1,但是從此類型轉換爲int應該會產生一個轉換警告(如果將編譯器配置爲高度冗長)。

總結: 它們都是相似的,但是當使用枚舉時,您可以使用類型檢查並通過使用定義您只需替換代碼字符串。

+1

「從這種類型爲int鑄造」是後到前,我想; C++將枚舉視爲int的特化。 – 2008-09-26 00:09:09

1

如果你有一組常量(比如「星期幾」),枚舉將是可取的,因爲它表明它們是分組的;正如傑森所說,他們是類型安全的。如果它是一個全局常量(如版本號),那更多的是使用#define;儘管這是很多辯論的主題。

14

#define語句在編譯器看到代碼之前由預處理器處理,因此它基本上是一個文本替換(它實際上使用參數等更智能一些)。

枚舉是C語言本身的一部分,具有以下優點。

1 /它們可能有類型,編譯器可以對它們進行類型檢查。因爲編譯器可以使用它們,所以它們上的符號信息可以傳遞給調試器,使調試變得更容易。

5

枚舉一般都超過者優先的#define無論是很有意義的使用枚舉:

  • 調試器可以告訴你一個enum價值(「openType: OpenExisting」的符號名稱,而不是‘openType: 2
  • 你從名稱衝突,多一點保障,但是這並不是那麼糟糕,因爲它是(大多數編譯器警告重新#define銀行足球比賽。

最大的區別是,喲ü可以使用枚舉類型爲:

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

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

這給你的參數類型檢查(你不能混淆一樣容易OpenType和緩衝區大小),並可以很容易地找到什麼值是有效的,使你的界面更容易使用。一些IDE甚至可以給你 intellisense 代碼完成!

1

除了上面列出的優點之外,您還可以將枚舉的範圍限制爲類,結構或命名空間。就我個人而言,我喜歡在任何一個時間都有最小數量的相關符號,這是使用枚舉而不是#define的另一個原因。

1

enum在定義列表上的另一個優點是編譯器(至少gcc)可以在switch語句中沒有檢查所有值時生成警告。例如:

enum { 
    STATE_ONE, 
    STATE_TWO, 
    STATE_THREE 
}; 

... 

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

在前面的代碼,編譯器能夠產生,並非所有的枚舉值在開關被處理的警告。如果這些狀態是以#define的形式完成的,情況就不會如此。

4

如果可能,最好使用枚舉。使用枚舉爲編譯器提供了關於源代碼的更多信息,預編譯器定義從未被編譯器看到,因此信息量少。

爲了實現例如例如,使用枚舉的一堆模式使編譯器能夠在交換機中捕獲缺失的case -statements。

1

枚舉更多地用於枚舉某種集合,比如一週中的幾天。如果你只需要一個常數,const int(或double等)將比enum更好。我個人不喜歡#define(至少不是爲了定義一些常量),因爲它不能給我類型安全,但是如果它更適合你,當然可以使用它。

2

如果你只想要這個單一常量(比如緩衝區大小),那麼我不會使用枚舉,而是一個定義。我會使用枚舉來獲取返回值(這意味着不同的錯誤條件)以及我們需要區分不同「類型」或「案例」的地方。在這種情況下,我們可以使用枚舉來創建一個我們可以在函數原型等中使用的新類型,然後編譯器可以更好地檢查代碼。

3

枚舉罐組中的一個類別的多個元素:

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

而#定義只能創建無關的常量:

#define apple 1234 
#define orange 12345 
+0

謝謝你在互聯網上最有用的答案。 (並且我真的不是在開玩笑) – 2013-09-05 05:05:08

3

的#define是預處理器的命令,枚舉在C或C++語言。

在這種情況下使用枚舉超過#define總是更好。一件事是類型安全。另一個原因是當你有一系列值時,你只需要在枚舉中給出序列的開始,其他值就是連續的值。

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

代替

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

作爲一個側面說明,仍有一定的情況下,您可能需要使用的#define(通常爲某種宏,如果你需要能夠構建一個包含常量的標識符),但這是一種宏觀的黑魔法,而且非常非常罕見。如果你去了這些極端,你可能應該使用C++模板(但是如果你堅持使用C ...)。

2

除了所有已經寫好的東西,一個說,但沒有顯示,而是有趣的。例如。

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

考慮作爲一種類型的行爲可以讓事情更清楚。使用定義,你會寫

void do_action(int anAction, info_t x); 
2

對於我來喜歡enum超過#define整型常量的值。使用enum似乎沒有任何缺點(折扣更多打字的小小缺點),但是您的優勢是enum可以作用域,而#define標識符具有全局範圍,可以推翻所有內容。

使用#define通常不是一個問題,但由於enum沒有缺點,我就這樣做了。

在C++中我也一般喜歡enumconst int即使在C++中const int來代替文字整數值(在C不同)中使用,因爲enum移植到C(我仍然有很多工作)。

1

創建一個枚舉不僅會創建文字,還會創建對這些文字進行分組的類型:這可以增加編譯器能夠檢查的代碼的語義。

此外,使用調試器時,您可以訪問枚舉文字的值。 #define並非總是如此。

0

沒有什麼區別。 C標準說枚舉具有整型,而枚舉常量的類型爲int,所以它們可以與其他整型自由混合,沒有錯誤。 (另一方面,如果沒有明確的轉換就不允許這種混合,明智地使用枚舉可能會遇到某些編程錯誤。)

枚舉的一些優點是數值自動分配,調試器可以在檢查枚舉變量時顯示符號值,並且它們遵守塊範圍。 (編譯器也可能會產生非致命警告時所列舉的都是胡亂混合,因爲這樣做仍然可以被認爲是不好的風格,即使它不是嚴格非法的。)一個缺點是程序員可以對這些非致命警告進行控制;一些程序員也怨恨不能控制枚舉變量的大小。

0

雖然以上幾個答案建議使用各種原因枚舉,我想指出的是,使用定義開發接口時具有實際的優勢。您可以引入新的選項,並且可以讓軟件有條件地使用它們。

例如:

 

    #define OPT_X1 1 /* introduced in version 1 */ 
    #define OPT_X2 2 /* introduced in version 2 */ 

然後可與任一版本的編譯軟件,它可以做

 

    #ifdef OPT_X2 
    int flags = OPT_X2; 
    #else 
    int flags = 0; 
    #endif 

,同時在枚舉這也不是沒有可能運行時特徵檢測機制。

1

枚舉:

1.一般用於多個值

2.在枚舉有兩種事情之一是名稱和另一個是名稱的名稱的值必須加以區分,但其值可以是相同。如果我們沒有定義值,那麼枚舉名的第一個值是0秒的值是1,依此類推,除非指定了明確的值。

他們可能有類型和編譯器可以輸入檢查他們

4.使調試容易

5.我們可以限制它的範圍可達一類。

定義:

當我們定義只有一個值

2.它通常用一個字符串替換另一個字符串。

其範圍是全球性,我們不能限制其範圍

總體而言,我們必須使用枚舉