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

定义是一个预处理命令,它就像在你的编辑器中做“全部替换”一样,它可以用另一个字符串替换一个字符串然后编译结果。

枚举是类型的一种特殊情况,例如,如果你写:

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

存在一种称为 ERROR_TYPES 的新类型。REGULAR_ERR 确实会产生 1,但从这种类型转换为 int 应该会产生转换警告(如果您将编译器配置为高详细度)。

总结:它们都是相似的,但是当使用 enum 时,您可以从类型检查中受益,而通过使用定义,您只需替换代码字符串。

于 2008-09-25T23:53:15.857 回答
6

在使用枚举有意义的地方,枚举通常比#define 更受欢迎:

  • enum调试器可以向您显示s 值的符号名称(“ openType: OpenExisting”,而不是“ openType: 2
  • 您可以从名称冲突中获得更多保护,但这并没有以前那么糟糕(大多数编译器警告#definereition.

最大的区别是您可以使用枚举作为类型:

// 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

如果可能,最好使用枚举。使用枚举为编译器提供了有关您的源代码的更多信息,编译器永远不会看到预处理器定义,因此携带的信息更少。

例如,为了实现例如一堆模式,使用枚举使编译器可以捕获case开关中缺失的语句。

于 2010-06-14T07:28:26.213 回答
4

enum 可以将多个元素归为一类:

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

而#define 只能创建不相关的常量:

#define apple 1234
#define orange 12345
于 2010-06-14T07:34:02.987 回答
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 卡住了......)。

于 2010-06-14T07:38:51.803 回答
2

如果你只想要这个单一的常量(比如缓冲区大小),那么我不会使用枚举,而是使用定义。我会将枚举用于返回值(这意味着不同的错误条件)以及我们需要区分不同“类型”或“案例”的地方。在这种情况下,我们可以使用枚举来创建可以在函数原型等中使用的新类型,然后编译器可以更好地检查代码。

于 2010-06-14T07:31:38.870 回答
2

除了所有已经写好的东西,一个说但没有显示,而是很有趣。例如

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++ 中,我通常也更喜欢enum即使const int在 C++ 中 aconst int可以用来代替文字整数值(与 C 中不同),因为enum它可以移植到 C 中(我仍然在很多地方工作)。

于 2010-06-14T07:53:50.817 回答
1

如果您有一组常量(例如“星期几”),则最好使用枚举,因为它表明它们是分组的;而且,正如 Jason 所说,它们是类型安全的。如果它是一个全局常量(如版本号),那更多的是你要使用的#define;虽然这是很多争论的主题。

于 2008-09-25T23:54:04.187 回答
1

除了上面列出的优点之外,您还可以将枚举的范围限制为类、结构或命名空间。就个人而言,我喜欢在任何时候都在范围内拥有最少数量的相关符号,这是使用枚举而不是#defines 的另一个原因。

于 2008-09-26T10:37:15.107 回答
1

枚举相对于定义列表的另一个优点是编译器(至少 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 的方式完成的,则情况并非如此。

于 2008-09-29T01:32:22.510 回答
1

枚举更多地用于枚举某种集合,例如一周中的几天。如果您只需要一个常数,const int(或双倍等)肯定会比枚举更好。我个人不喜欢#define(至少不喜欢某些常量的定义),因为它没有给我类型安全,但如果它更适合你,你当然可以使用它。

于 2010-06-14T07:30:08.013 回答
1

创建枚举不仅会创建文字,还会创建对这些文字进行分组的类型:这为您的代码添加了编译器能够检查的语义。

此外,在使用调试器时,您可以访问枚举文字的值。#define 并非总是如此。

于 2010-06-14T08:13:50.890 回答
1

虽然上面的几个答案出于各种原因建议使用枚举,但我想指出,在开发接口时使用定义具有实际优势。您可以引入新选项,并且可以让软件有条件地使用它们。

例如:

    #define OPT_X1 1 /* 在版本 1 中引入 */
    #define OPT_X2 2 /* 在版本 2 中引入 */

然后可以用它可以做的任何一个版本编译的软件

    #ifdef OPT_X2
    int 标志 = OPT_X2;
    #别的
    整数标志 = 0;
    #万一

在枚举时,如果没有运行时特征检测机制,这是不可能的。

于 2016-07-20T11:00:50.957 回答
1

枚举:

1.一般用于多个值

2.在枚举中有两个东西一个是名称,另一个是名称的值 name 必须区分但 value 可以相同。如果我们不定义 value 那么 enum name 的第一个值是 0 秒value 为 1,依此类推,除非明确指定 value。

3.它们可能有类型,编译器可以对它们进行类型检查

4.使调试变得容易

5.我们可以将它的范围限制为一个类。

定义:

1.当我们只需要定义一个值时

2.一般将一个字符串替换为另一个字符串。

3.它的作用域是全局的,我们不能限制它的作用域

总的来说,我们必须使用枚举

于 2017-08-11T18:08:38.573 回答
0

差别不大。C 标准说枚举具有整数类型并且枚举常量是 int 类型,因此两者都可以与其他整数类型自由混合,而不会出错。(另一方面,如果在没有显式转换的情况下不允许这种混合,那么明智地使用枚举可能会发现某些编程错误。)

枚举的一些优点是数字值是自动分配的,调试器可以在检查枚举变量时显示符号值,并且它们服从块范围。(当枚举被不加选择地混合时,编译器也可能产生非致命警告,因为这样做仍然被认为是不好的风格,即使它不是严格非法的。)缺点是程序员几乎无法控制这些非致命警告。一些程序员也讨厌无法控制枚举变量的大小。

于 2014-06-23T13:38:31.227 回答