枚举和定义语句之间的区别
在C / C ++中使用define语句和enum语句有什么区别(与C或者C ++一起使用时有什么区别)?
例如,什么时候应该使用
enum {BUFFER = 1234};
超过
#define BUFFER 1234
解决方案
"枚举"定义了一个语法元素。
#define是一个预处理程序指令,在编译器看到代码之前执行,因此不是C本身的语言元素。
通常,枚举是首选的,因为它们是类型安全的并且更容易发现。定义很难定位并且具有复杂的行为,例如,一段代码可以重新定义另一段代码的" #define"。这可能很难追踪。
Define是一个预处理程序命令,就像在编辑器中执行"全部替换"一样,它可以用另一个替换字符串,然后编译结果。
枚举是类型的一种特殊情况,例如,如果我们编写:
enum ERROR_TYPES { REGULAR_ERR =1, OK =0 }
存在一个名为ERROR_TYPES的新类型。
确实REGULAR_ERR的结果为1,但是从此类型强制转换为int应该会产生强制转换警告(如果将编译器配置为高详细级别)。
概括:
它们都是相似的,但是使用枚举时,类型检查和定义都可以使我们简单地替换代码字符串。
如果我们有一组常量(例如"星期几"),则枚举会更可取,因为它表明它们已分组;而且,正如Jason所说,它们是类型安全的。如果它是一个全局常量(如版本号),那将是我们使用#define
的更多内容;尽管这是很多辩论的主题。
#define语句是在编译器看到代码之前由预处理程序处理的,因此它基本上是文本替换(实际上,使用参数等会更智能)。
枚举是C语言本身的一部分,具有以下优点。
1 /它们可能具有类型,编译器可以对其进行类型检查。
2 /由于编译器可以使用它们,因此有关它们的符号信息可以传递给调试器,从而使调试更加容易。
通常在需要使用枚举的任何地方都比#define更喜欢枚举:
- 调试器可以为我们显示一个枚举值的符号名称(" openType:OpenExisting`",而不是" openType:2"。
- 我们可以获得更多的名称冲突保护,但这并不像以前那样糟糕(大多数编译器警告有关重新定义名称的问题。
最大的区别是我们可以将枚举用作类型:
// Yeah, dumb example enum OpenType { OpenExisting, OpenOrCreate, Truncate }; void OpenFile(const char* filename, OpenType openType, int bufferSize);
这使我们可以对参数进行类型检查(不能轻易混合使用openType和bufferSize),并且可以轻松地找到有效的值,从而使接口的使用更加容易。某些IDE甚至可以为我们提供智能的代码完成功能!
除了上面列出的优点之外,我们还可以将枚举的范围限制为类,结构或者名称空间。就个人而言,我希望每次都在作用域中使用最少数量的事件符号,这是使用枚举而非#defines的另一个原因。
与定义列表相比,枚举的另一个优点是,当未在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进行的,则情况并非如此。
如果可能的话,最好使用枚举。使用枚举为编译器提供了有关源代码的更多信息,编译器从未看到过预处理器定义,因此携带的信息较少。
用于实施一堆模式,使用枚举可以使编译器例如在开关中捕获丢失的" case"语句。
枚举通常用于枚举某种类型的集合,例如一周中的几天。如果只需要一个常数,则const int(或者double等)肯定比枚举更好。我个人不喜欢#define
(至少不喜欢某些常量的定义),因为它不能为我提供类型安全性,但是我们当然可以使用它,如果它更适合我们。
如果只想使用这个常量(比如说buffersize),那么我就不会使用枚举,而应该使用定义。我将枚举用于返回值(表示不同的错误条件)之类的东西,以及需要区分不同的"类型"或者"案例"的地方。在那种情况下,我们可以使用一个枚举创建一个可以在函数原型等中使用的新类型,然后编译器可以更好地检查该代码。
枚举可以将多个元素归为一类:
enum fruits{ apple=1234, orange=12345};
而#define只能创建不相关的常量:
#define apple 1234 #define orange 12345
#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 ...)。
除了已经写过的所有东西,一个人说了但没有显示,反而很有趣。例如。
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);
对于整数常量值,相对于#define,我更倾向于使用enum。使用enum
似乎没有缺点(减少了更多键入的微小缺点),但是优点是enum
可以范围化,而#define`标识符具有全局性,这使一切变得麻烦。
通常使用#define并不是问题,但是由于enum没有任何缺点,因此我同意了。
在C ++中,尽管在C ++中,const int
可以代替文字整数值使用(与C语言不同),但我通常也更喜欢使用" enum"而不是" const int",因为enum
可以移植到C语言中(我仍然可以工作很多)。
创建枚举不仅会创建文字,还会创建对这些文字进行分组的类型:这将使语义增加到编译器能够检查的代码中。
此外,在使用调试器时,我们可以访问枚举文字的值。 #define并非总是如此。