枚举和定义语句之间的区别

发布于 2024-09-05 12:27:47 字数 195 浏览 2 评论 0原文

在 C/C++ 中使用 Define 语句和 enum 语句有什么区别(在 C 或 C++ 中使用它们时有什么区别)?

例如,什么时候应该使用

enum {BUFFER = 1234}; 

超过

#define BUFFER 1234   

What's the difference between using a define statement and an enum statement in C/C++ (and is there any difference when using them with either C or C++)?

For example, when should one use

enum {BUFFER = 1234}; 

over

#define BUFFER 1234   

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

翻身的咸鱼 2024-09-12 12:27:47

enum 定义语法元素。

#define 是一个预处理器指令,在编译器看到代码之前执行,因此不是 C 本身的语言元素。

一般来说,枚举是首选,因为它们是类型安全的并且更容易发现。定义更难定位并且可能具有复杂的行为,例如一段代码可以重新定义另一段代码创建的#define。这可能很难追踪。

enum defines a syntactical element.

#define is a pre-preprocessor directive, executed before the compiler sees the code, and therefore is not a language element of C itself.

Generally enums are preferred as they are type-safe and more easily discoverable. Defines are harder to locate and can have complex behavior, for example one piece of code can redefine a #define made by another. This can be hard to track down.

策马西风 2024-09-12 12:27:47

#define 语句在编译器看到代码之前由预处理器处理,因此它基本上是文本替换(实际上使用参数等更加智能)。

枚举是C语言本身的一部分,具有以下优点。

1/ 它们可能有类型,编译器可以对它们进行类型检查。

2/ 由于它们可供编译器使用,因此它们的符号信息可以传递给调试器,从而使调试更容易。

#define statements are handled by the pre-processor before the compiler gets to see the code so it's basically a text substitution (it's actually a little more intelligent with the use of parameters and such).

Enumerations are part of the C language itself and have the following advantages.

1/ They may have type and the compiler can type-check them.

2/ Since they are available to the compiler, symbol information on them can be passed through to the debugger, making debugging easier.

南笙 2024-09-12 12:27:47

在任何需要使用枚举的地方,枚举通常比 #define 更受青睐:

  • 调试器可以向您显示 enum 值的符号名称(“openType: OpenExisting”,而不是与“openType: 2”相比,
  • 您可以在名称冲突方面获得更多保护,但这并不像以前那么糟糕(大多数编译器都会警告重新#defineition。

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

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

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

这使您可以对参数进行类型检查(您不能轻易混淆 openType 和 bufferSize),并且可以轻松找到有效的值,从而使您的界面更加容易有些 IDE 甚至可以为您提供 intellisense 代码补全!

Enums are generally prefered over #define wherever it makes sense to use an enum:

  • Debuggers can show you the symbolic name of an enums value ("openType: OpenExisting", rather than "openType: 2"
  • You get a bit more protection from name clashes, but this isn't as bad as it was (most compilers warn about re#defineition.

The biggest difference is that you can use enums as types:

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

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

This gives you type-checking of parameters (you can't mix up openType and bufferSize as easily), and makes it easy to find what values are valid, making your interfaces much easier to use. Some IDEs can even give you intellisense code completion!

旧人哭 2024-09-12 12:27:47

Define是一个预处理器命令,就像在编辑器中执行“全部替换”一样,它可以将一个字符串替换为另一个字符串,然后编译结果。

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

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

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

概括:
它们都很相似,但是当使用枚举时,您可以进行类型检查,而通过使用定义,您只需替换代码字符串即可。

Define is a preprocessor command, it's just like doing "replace all" in your editor, it can replace a string with another and then compile the result.

Enum is a special case of type, for example, if you write:

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

there exists a new type called ERROR_TYPES.
It is true that REGULAR_ERR yields to 1 but casting from this type to int should produce a casting warning (if you configure your compiler to high verbosity).

Summary:
they are both alike, but when using enum you profit the type checking and by using defines you simply replace code strings.

若无相欠,怎会相见 2024-09-12 12:27:47

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

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

It's always better to use an enum if possible. Using an enum gives the compiler more information about your source code, a preprocessor define is never seen by the compiler and thus carries less information.

For implementing e.g. a bunch of modes, using an enum makes it possible for the compiler to catch missing case-statements in a switch, for instance.

却一份温柔 2024-09-12 12:27:47

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

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

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

#define apple 1234
#define orange 12345

enum can group multiple elements in one category:

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

while #define can only create unrelated constants:

#define apple 1234
#define orange 12345
江城子 2024-09-12 12:27:47

#define 是一个预处理器命令,enum 使用 C 或 C++ 语言。

对于这种情况,使用 enum 总是比 #define 更好。一件事是类型安全。另一个问题是,当您有一系列值时,您只需在枚举中给出序列的开头,其他值将获得连续的值。

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

作为

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

旁注,在某些情况下您可能必须使用#define(通常对于某种宏,如果您需要能够构造包含常量的标识符),但这是一种宏黑魔法,而且非常罕见。如果您走到这些极端,您可能应该使用 C++ 模板(但如果您坚持使用 C...)。

#define is a preprocessor command, enum is in the C or C++ language.

It is always better to use enums over #define for this kind of cases. One thing is type safety. Another one is that when you have a sequence of values you only have to give the beginning of the sequence in the enum, the other values get consecutive values.

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

instead of

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

As a side-note, there is still some cases where you may have to use #define (typically for some kind of macros, if you need to be able to construct an identifier that contains the constant), but that's kind of macro black magic, and very very rare to be the way to go. If you go to these extremities you probably should use a C++ template (but if you're stuck with C...).

檐上三寸雪 2024-09-12 12:27:47

枚举相对于定义列表的另一个优点是,当未在 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;
};

在前面的代码中,编译器能够生成警告,指出并非所有枚举值都在 switch 中处理。如果状态按照#define 完成,情况就不会是这样。

Another advantage of an enum over a list of defines is that compilers (gcc at least) can generate a warning when not all values are checked in a switch statement. For example:

enum {
    STATE_ONE,
    STATE_TWO,
    STATE_THREE
};

...

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

In the previous code, the compiler is able to generate a warning that not all values of the enum are handled in the switch. If the states were done as #define's, this would not be the case.

治碍 2024-09-12 12:27:47

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

If you only want this single constant (say for buffersize) then I would not use an enum, but a define. I would use enums for stuff like return values (that mean different error conditions) and wherever we need to distinguish different "types" or "cases". In that case we can use an enum to create a new type we can use in function prototypes etc., and then the compiler can sanity check that code better.

遮了一弯 2024-09-12 12:27:47

除了已经写过的所有内容之外,还有一个说了但没有显示出来的内容,反而很有趣。例如,

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);

Besides all the thing already written, one said but not shown and is instead interesting. E.g.

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

Considering action as a type makes thing clearer. Using define, you would have written

void do_action(int anAction, info_t x);
心碎无痕… 2024-09-12 12:27:47

对于整数常量值,我更喜欢 enum 而不是 #define。使用 enum 似乎没有任何缺点(忽略了多输入一点的微小缺点),但你有一个优点,即 enum 可以限定范围,而 #define 标识符具有超越一切的全局范围。

使用#define 通常不会有问题,但由于 enum 没有缺点,所以我同意这样做。

在 C++ 中,我通常也更喜欢 enum 而不是 const int,即使在 C++ 中,可以使用 const int 代替文字整数值(与在 C 中),因为 enum 可以移植到 C(我仍然经常使用 C)。

For integral constant values I've come to prefer enum over #define. There seem to be no disadvantages to using enum (discounting the miniscule disadvantage of a bit more typing), but you have the advantage that enum can be scoped, while #define identifiers have global scope that tromps everything.

Using #define isn't usually a problem, but since there are no drawbacks to enum, I go with that.

In C++ I also generally prefer enum to const int even though in C++ a const int can be used in place of a literal integer value (unlike in C) because enum is portable to C (which I still work in a lot) .

み格子的夏天 2024-09-12 12:27:47

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

If you have a group of constants (like "Days of the Week") enums would be preferable, because it shows that they are grouped; and, as Jason said, they are type-safe. If it's a global constant (like version number), that's more what you'd use a #define for; although this is the subject of a lot of debate.

陪你到最终 2024-09-12 12:27:47

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

In addition to the good points listed above, you can limit the scope of enums to a class, struct or namespace. Personally, I like to have the minimum number of relevent symbols in scope at any one time which is another reason for using enums rather than #defines.

薯片软お妹 2024-09-12 12:27:47

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

enums are more used for enumerating some kind of set, like days in a week. If you need just one constant number, const int (or double etc.) would be definetly better than enum. I personally do not like #define (at least not for the definition of some constants) because it does not give me type safety, but you can of course use it if it suits you better.

北风几吹夏 2024-09-12 12:27:47

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

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

Creating an enum creates not only literals but also the type that groups these literals: This adds semantic to your code that the compiler is able to check.

Moreover, when using a debugger, you have access to the values of enum literals. This is not always the case with #define.

心意如水 2024-09-12 12:27:47

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

例如:

    #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

在枚举上执行此操作,如果没有运行时功能检测机制,这是不可能的。

While several answers above recommend to use enum for various reasons, I'd like to point out that using defines has an actual advantage when developing interfaces. You can introduce new options and you can let software use them conditionally.

For example:

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

Then software which can be compiled with either version it can do

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

While on an enumeration this isn't possible without a run-time feature detection mechanism.

魂ガ小子 2024-09-12 12:27:47

枚举:

1. 一般用于多个值

2. 在枚举中,有两件事,一个是名称,另一个是名称的值,名称必须区分,但值可以相同。如果我们不定义值,则枚举名称的第一个值是 0 第二个值是1,依此类推,除非明确指定值。

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

4.让调试变得简单

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

定义:

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

2.它通常将一个字符串替换为另一个字符串。

3.它的范围是全局的,我们无法限制它的范围

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

Enum:

1. Generally used for multiple values

2. In enum there are two thing one is name and another is value of name name must be distinguished but value can be same.If we not define value then first value of enum name is 0 second value is 1,and so on, unless explicitly value are specified.

3. They may have type and compiler can type check them

4. Make debugging easy

5. We can limit scope of it up to a class.

Define:

1. When we have to define only one value

2. It generally replace one string to another string.

3. It scope is global we cannot limit its scope

Overall we have to use enum

时光沙漏 2024-09-12 12:27:47

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

枚举的一些优点是数字值是自动分配的,调试器可以显示符号检查枚举变量时的值,并且它们遵守块作用域。 (当枚举不加区别地混合时,编译器也可能生成非致命警告,因为这样做仍然可以被认为是不好的风格,即使它不是严格非法的。)缺点是程序员对这些非致命警告几乎没有控制权;一些程序员还对无法控制枚举变量的大小感到不满。

There is little difference. The C Standard says that enumerations have integral type and that enumeration constants are of type int, so both may be freely intermixed with other integral types, without errors. (If, on the other hand, such intermixing were disallowed without explicit casts, judicious use of enumerations could catch certain programming errors.)

Some advantages of enumerations are that the numeric values are automatically assigned, that a debugger may be able to display the symbolic values when enumeration variables are examined, and that they obey block scope. (A compiler may also generate nonfatal warnings when enumerations are indiscriminately mixed, since doing so can still be considered bad style even though it is not strictly illegal.) A disadvantage is that the programmer has little control over those nonfatal warnings; some programmers also resent not having control over the sizes of enumeration variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文