2008-09-25 88 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.它通常用一个字符串替换另一个字符串。

其范围是全球性,我们不能限制其范围

总体而言,我们必须使用枚举