在 C/C++ 中使用 define 语句和 enum 语句有什么区别(在 C 或 C++ 中使用它们时有什么区别)?
例如,什么时候应该使用
enum {BUFFER = 1234};
超过
#define BUFFER 1234
在 C/C++ 中使用 define 语句和 enum 语句有什么区别(在 C 或 C++ 中使用它们时有什么区别)?
例如,什么时候应该使用
enum {BUFFER = 1234};
超过
#define BUFFER 1234
enum
定义一个句法元素。
#define
是预处理器指令,在编译器看到代码之前执行,因此不是 C 本身的语言元素。
一般来说,枚举是首选,因为它们是类型安全的并且更容易被发现。定义更难定位并且可能具有复杂的行为,例如一段代码可以重新定义#define
另一段代码。这可能很难追踪。
#define
语句在编译器查看代码之前由预处理器处理,因此它基本上是文本替换(实际上使用参数等更智能)。
枚举是 C 语言本身的一部分,具有以下优点。
1/ 它们可能有类型,编译器可以对它们进行类型检查。
2/ 由于它们对编译器可用,它们的符号信息可以传递给调试器,使调试更容易。
定义是一个预处理命令,它就像在你的编辑器中做“全部替换”一样,它可以用另一个字符串替换一个字符串然后编译结果。
枚举是类型的一种特殊情况,例如,如果你写:
enum ERROR_TYPES
{
REGULAR_ERR =1,
OK =0
}
存在一种称为 ERROR_TYPES 的新类型。REGULAR_ERR 确实会产生 1,但从这种类型转换为 int 应该会产生转换警告(如果您将编译器配置为高详细度)。
总结:它们都是相似的,但是当使用 enum 时,您可以从类型检查中受益,而通过使用定义,您只需替换代码字符串。
在使用枚举有意义的地方,枚举通常比#define 更受欢迎:
enum
调试器可以向您显示s 值的符号名称(“ openType: OpenExisting
”,而不是“ openType: 2
”#define
reition.最大的区别是您可以使用枚举作为类型:
// Yeah, dumb example
enum OpenType {
OpenExisting,
OpenOrCreate,
Truncate
};
void OpenFile(const char* filename, OpenType openType, int bufferSize);
这使您可以对参数进行类型检查(您不能轻易混淆 openType 和 bufferSize),并且可以轻松找到有效的值,从而使您的接口更易于使用。一些 IDE 甚至可以为您提供智能感知代码完成功能!
如果可能,最好使用枚举。使用枚举为编译器提供了有关您的源代码的更多信息,编译器永远不会看到预处理器定义,因此携带的信息更少。
例如,为了实现例如一堆模式,使用枚举使编译器可以捕获case
开关中缺失的语句。
enum 可以将多个元素归为一类:
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);
对于整数常量值,我更enum
喜欢#define
. 使用似乎没有任何缺点enum
(排除更多打字的微小缺点),但是您具有enum
可以限定范围的优势,而#define
标识符具有超越一切的全局范围。
使用#define
通常不是问题,但由于没有缺点enum
,我同意。
在 C++ 中,我通常也更喜欢enum
即使const int
在 C++ 中 aconst int
可以用来代替文字整数值(与 C 中不同),因为enum
它可以移植到 C 中(我仍然在很多地方工作)。
如果您有一组常量(例如“星期几”),则最好使用枚举,因为它表明它们是分组的;而且,正如 Jason 所说,它们是类型安全的。如果它是一个全局常量(如版本号),那更多的是你要使用的#define
;虽然这是很多争论的主题。
除了上面列出的优点之外,您还可以将枚举的范围限制为类、结构或命名空间。就个人而言,我喜欢在任何时候都在范围内拥有最少数量的相关符号,这是使用枚举而不是#defines 的另一个原因。
枚举相对于定义列表的另一个优点是编译器(至少 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 的方式完成的,则情况并非如此。
枚举更多地用于枚举某种集合,例如一周中的几天。如果您只需要一个常数,const int
(或双倍等)肯定会比枚举更好。我个人不喜欢#define
(至少不喜欢某些常量的定义),因为它没有给我类型安全,但如果它更适合你,你当然可以使用它。
创建枚举不仅会创建文字,还会创建对这些文字进行分组的类型:这为您的代码添加了编译器能够检查的语义。
此外,在使用调试器时,您可以访问枚举文字的值。#define 并非总是如此。
虽然上面的几个答案出于各种原因建议使用枚举,但我想指出,在开发接口时使用定义具有实际优势。您可以引入新选项,并且可以让软件有条件地使用它们。
例如:
#define OPT_X1 1 /* 在版本 1 中引入 */ #define OPT_X2 2 /* 在版本 2 中引入 */
然后可以用它可以做的任何一个版本编译的软件
#ifdef OPT_X2 int 标志 = OPT_X2; #别的 整数标志 = 0; #万一
在枚举时,如果没有运行时特征检测机制,这是不可能的。
枚举:
1.一般用于多个值
2.在枚举中有两个东西一个是名称,另一个是名称的值 name 必须区分但 value 可以相同。如果我们不定义 value 那么 enum name 的第一个值是 0 秒value 为 1,依此类推,除非明确指定 value。
3.它们可能有类型,编译器可以对它们进行类型检查
4.使调试变得容易
5.我们可以将它的范围限制为一个类。
定义:
1.当我们只需要定义一个值时
2.一般将一个字符串替换为另一个字符串。
3.它的作用域是全局的,我们不能限制它的作用域
总的来说,我们必须使用枚举
差别不大。C 标准说枚举具有整数类型并且枚举常量是 int 类型,因此两者都可以与其他整数类型自由混合,而不会出错。(另一方面,如果在没有显式转换的情况下不允许这种混合,那么明智地使用枚举可能会发现某些编程错误。)
枚举的一些优点是数字值是自动分配的,调试器可以在检查枚举变量时显示符号值,并且它们服从块范围。(当枚举被不加选择地混合时,编译器也可能产生非致命警告,因为这样做仍然被认为是不好的风格,即使它不是严格非法的。)缺点是程序员几乎无法控制这些非致命警告。一些程序员也讨厌无法控制枚举变量的大小。