枚举与定义语句的区别
在C / C ++中使用define语句和enum语句有什么区别(和C或C ++一起使用它们有什么区别)?
例如,什么时候应该使用
enum {BUFFER = 1234};
过度
#define BUFFER 1234
enum
定义了一个语法元素。
#define
是一个预处理器指令, 在编译器看到代码之前执行,因此不是C本身的语言元素。
通常枚举是首选,因为它们是types安全的,更容易发现。 定义很难find并且可能有复杂的行为,例如,一段代码可以重新定义另一个定义的#define
。 这可能很难追查。
#define
语句在编译器看到代码之前由预处理器处理,所以它基本上是一个文本replace(实际上它使用参数等更智能一些)。
枚举是C语言本身的一部分,具有以下优点。
1 /他们可能有types,编译器可以键入检查它们。
2 /由于编译器可以使用它们,所以它们上面的符号信息可以传递给debugging器,使debugging更容易。
Define是一个预处理器命令,就像在编辑器中“replace全部”一样,它可以用另一个stringreplace一个string,然后编译结果。
例如,Enum是一个特殊的types,如果你写:
enum ERROR_TYPES { REGULAR_ERR =1, OK =0 }
存在称为ERROR_TYPES的新types。 确实REGULAR_ERR的结果是1,但是从这个types转换为int应该会产生一个转换警告(如果你把编译器configuration的很高)。
总结:它们都是相似的,但是在使用枚举的时候,你可以通过types检查来获得利益,通过定义你可以简单地replace代码string。
枚举通常优先于#define,只要使用enum有意义:
- debugging器可以显示一个
enum
值(“openType: OpenExisting
”)的符号名称,而不是“openType: 2
” - 你可以从名称冲突中得到更多的保护,但是这并没有那么糟糕(大多数编译器都会对
#define
ition提出警告。
最大的区别是你可以使用枚举types:
// Yeah, dumb example enum OpenType { OpenExisting, OpenOrCreate, Truncate }; void OpenFile(const char* filename, OpenType openType, int bufferSize);
这使您可以对参数进行types检查(不能混淆openType和bufferSize),并且可以很容易地find哪些值是有效的,从而使您的接口更容易使用。 一些IDE甚至可以让你完成智能代码!
如果可能,最好使用枚举。 使用枚举为编译器提供了关于源代码的更多信息,编译器从不会看到预处理器的定义,从而携带更less的信息。
例如,为了实现一堆模式,使用枚举可以使编译器在交换机中捕获缺less的case
-statements。
枚举可以将多个元素分组在一个类别中:
enum fruits{ apple=1234, orange=12345};
而#define只能创build不相关的常量:
#define apple 1234 #define orange 12345
#define是一个预处理器命令,枚举是C或C ++语言。
在这种情况下使用#define的枚举总是更好。 一件事是types安全。 另一个是,当你有一个值的序列,你只需要在枚举的序列的开始,其他值得到连续的值。
enum { ONE = 1, TWO, THREE, FOUR };
代替
#define ONE 1 #define TWO 2 #define THREE 3 #define FOUR 4
作为一个侧面说明,还有一些情况下,你可能不得不使用#define(通常为某种macros,如果你需要能够构build一个包含常量的标识符),但这是一种macros观黑魔法,而且非常非常难得的是要走的路。 如果你去这些肢体,你可能应该使用一个C ++模板(但如果你坚持使用C …)。
如果你只想要这个单一的常量(比如缓冲区大小),那么我不会使用枚举,而是一个定义。 我会使用枚举的东西,如返回值(这意味着不同的错误条件),无论我们需要区分不同的“types”或“案件”。 在这种情况下,我们可以使用枚举来创build一个我们可以在函数原型等中使用的新types,然后编译器可以更好地检查代码。
除了所有已经写好的东西,一个说,但没有显示,而是有趣的。 例如
enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP }; //... void do_action( enum action anAction, info_t x );
考虑到作为一种types的行动使事情更清楚。 使用define,你会写
void do_action(int anAction, info_t x);
对于积分常量值,我更喜欢enum
#define
。 使用enum
似乎没有什么缺点(折扣多一点打字less的缺点),但是你有一个好处,就是enum
可以作用域,而#define
标识符具有全局作用域。
使用#define
通常不是一个问题,但是因为enum
没有缺点,所以我就这样做了。
在C ++中,我通常也更喜欢enum
const int
即使在C ++中, const int
可以用来代替文字整数值(不像在C中),因为enum
可移植到C(我仍然工作很多)。
如果你有一组常量(比如“星期几”),那么枚举将是可取的,因为它表明它们是分组的; 正如贾森所说,他们是types安全的。 如果它是一个全局常量(比如版本号),那么更多的是使用#define
; 虽然这是很多辩论的主题。
除了上面列出的优点以外,还可以将枚举的范围限制为一个类,结构或命名空间。 就我个人而言,我喜欢在任何时候都有最小数量的相关符号,这是使用枚举而不是#define的另一个原因。
enum超过一个定义列表的另一个好处是编译器(至lessgcc)可以在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的forms完成的,情况就不会如此。
枚举更多地用于枚举某种集合,如一周中的几天。 如果你只需要一个常量, const int
(或者double等)比enum要好。 我个人不喜欢#define
(至less不是为了定义一些常量),因为它不能给我types安全,但是如果它更适合你,当然可以使用它。
创build枚举不仅可以创build文字,还可以创build对这些文字进行分组的types:这可以增加编译器能够检查的代码的语义。
此外,使用debugging器时,您可以访问枚举文字的值。 #define并非总是如此。
枚举:
1.通常用于多个值
2.枚举中有两个名字是name,另一个是名字name的值必须区分,但value可以是相同的。如果我们没有定义value,那么枚举名的第一个值是0 second value是1,依此类推,除非明确指定值。
他们可能有types和编译器可以键入检查他们
4.使debugging容易
我们可以把它的范围限制在一个class级。
定义:
1.我们只需要定义一个值
它通常将一个stringreplace为另一个string。
它的范围是全球性的,我们不能限制它的范围
总的来说,我们必须使用枚举
没有什么区别。 C标准说枚举具有整型,而枚举常量是inttypes,所以它们可以和其他整型自由混合,没有错误。 (另一方面,如果没有明确的转换就不允许这样的混合,明智地使用枚举可能会遇到某些编程错误。)
枚举的一些优点是数值自动分配,debugging器可以在枚举variables被检查时显示符号值,并且它们遵守块范围。 (当枚举被不加区分地混合时,编译器也会产生非致命的警告,因为这样做可能仍然被认为是坏风格,即使它不是严格违法的。)缺点是程序员很less控制这些非致命的警告。 一些程序员也怨恨不能控制枚举variables的大小。
虽然上面的几个答案build议使用枚举的各种原因,我想指出的是,使用定义在开发接口时具有实际优势。 你可以引入新的选项,你可以让软件有条件地使用它们。
例如:
#define OPT_X1 1 / *在版本1中引入* / #define OPT_X2 2 / *在版本2中引入* /
然后可以用任何版本编译的软件都可以
#ifdef OPT_X2 int flags = OPT_X2; #其他 int flags = 0; #万一
枚举时,如果没有运行时特征检测机制,这是不可能的。