在C / C ++中使用define语句和枚举语句有什么区别(与C或C ++一起使用时有什么不同)?
例如,何时应该使用
enum {BUFFER = 1234};
在
#define BUFFER 1234
答案 0 :(得分:56)
enum
定义了一个语法元素。
#define
是一个预处理器指令,在编译器看到代码之前执行,因此不是C本身的语言元素。
通常优选枚举,因为它们是类型安全的并且更容易被发现。定义更难定位并且可能具有复杂的行为,例如,一段代码可以重新定义另一个代码生成的#define
。这很难追查。
答案 1 :(得分:17)
#define
语句,因此它基本上是一个文本替换(使用参数实际上更加智能化)。
枚举是C语言本身的一部分,具有以下优点。
1 /它们可能有类型,编译器可以对它们进行类型检查。
2 /由于它们可供编译器使用,因此它们上的符号信息可以传递给调试器,从而使调试更容易。
答案 2 :(得分:8)
Define是一个预处理器命令,它就像在编辑器中执行“replace all”,它可以用另一个字符串替换字符串,然后编译结果。
枚举是一种特殊的类型,例如,如果你写:
enum ERROR_TYPES
{
REGULAR_ERR =1,
OK =0
}
存在一种名为ERROR_TYPES的新类型。 确实REGULAR_ERR产生为1但是从这种类型转换为int应该产生一个转换警告(如果你将编译器配置为高详细程度)。
要点: 它们都是相似的,但是当使用枚举时,您可以获得类型检查,并且通过使用定义,您只需替换代码字符串。
答案 3 :(得分:5)
在使用枚举的任何地方,枚举通常都优先于#define:
enum
s值的符号名称(“openType: OpenExisting
”,而不是“openType: 2
”#define
ition。最大的区别是你可以使用枚举作为类型:
// Yeah, dumb example
enum OpenType {
OpenExisting,
OpenOrCreate,
Truncate
};
void OpenFile(const char* filename, OpenType openType, int bufferSize);
这为您提供了参数的类型检查(您不能轻易地混合使用openType和bufferSize),并且可以轻松找到哪些值有效,使您的界面更易于使用。有些IDE甚至可以给你 intellisense 代码完成!
答案 4 :(得分:4)
如果可能的话,最好使用枚举。使用枚举为编译器提供了有关源代码的更多信息,编译器从不会看到预处理器定义,因此信息量较少。
用于实施例如一堆模式,使用枚举使编译器可以捕获交换机中缺少的case
- 语句。例如。
答案 5 :(得分: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卡住了......)。
答案 6 :(得分:3)
枚举可以将一个类别中的多个元素分组:
enum fruits{ apple=1234, orange=12345};
而#define只能创建不相关的常量:
#define apple 1234
#define orange 12345
答案 7 :(得分:2)
如果你只想要这个单一的常量(比如对于buffersize)那么我就不会使用枚举,而是使用定义。我会使用枚举来表示返回值(表示不同的错误条件)以及我们需要区分不同“类型”或“案例”的地方。在这种情况下,我们可以使用枚举来创建我们可以在函数原型等中使用的新类型,然后编译器可以更好地检查该代码。
答案 8 :(得分:2)
对于积分常数值,我更喜欢enum
而不是#define
。使用enum
似乎没有任何缺点(折扣更多类型的微不足道的缺点),但你的优势是enum
可以作用域,而#define
标识符具有全局作用域那就是一切。
使用#define
通常不是问题,但由于enum
没有任何缺点,我会继续使用。
在C ++中,我通常也喜欢enum
到const int
,即使在C ++中,可以使用const int
代替文字整数值(与C不同),因为{{1}可以移植到C(我仍然可以使用它)。
答案 9 :(得分:2)
除了已经写过的所有内容之外,有人说但没有显示,而是有趣的。 E.g。
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);
答案 10 :(得分:1)
枚举更多地用于枚举某种类型的集合,例如一周中的日期。如果你只需要一个常数,const int
(或双倍等)肯定比枚举更好。我个人不喜欢#define
(至少不是某些常量的定义),因为它不能给我类型安全,但如果它更适合你,你当然可以使用它。
答案 11 :(得分:1)
枚举相对于定义列表的另一个优点是,当在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,那就不是这种情况。
答案 12 :(得分:1)
除了上面列出的优点之外,您还可以将枚举的范围限制为类,结构或命名空间。就个人而言,我喜欢在任何时候在范围内使用最少数量的相关符号,这是使用枚举而不是#defines的另一个原因。
答案 13 :(得分:1)
如果你有一组常量(比如“星期几”),那么枚举会更好,因为它表明它们是分组的;而且,正如杰森所说,它们是类型安全的。如果它是一个全局常量(如版本号),则更多的是你使用#define
;虽然这是很多争论的主题。
答案 14 :(得分:1)
创建枚举不仅会创建文字,还会创建对这些文字进行分组的类型:这会为编译器能够检查的代码添加语义。
此外,使用调试器时,您可以访问枚举文字的值。 #define并非总是如此。
答案 15 :(得分:1)
<强>枚举:强>
1。一般用于多个值
2. 在枚举中有一个是名称,另一个是名称的值必须区分但值可以相同。如果我们没有定义值那么枚举名称的第一个值是0秒值是1,依此类推,除非明确指定值。
3. 他们可能有类型,编译器可以打字检查它们
4. 使调试变得容易
5. 我们可以将其范围限制在一个级别。
<强>定义:强>
1。当我们只需定义一个值
时
2。它通常将一个字符串替换为另一个字符串。
3。范围是全球性的我们不能限制其范围
总的来说,我们必须使用枚举
答案 16 :(得分:0)
没有什么区别。 C标准表示枚举具有整数类型,枚举常量的类型为int,因此两者都可以与其他整数类型自由混合,没有错误。 (另一方面,如果在没有明确演员的情况下不允许这样的混合,明智地使用枚举可能会遇到某些编程错误。)
枚举的一些优点是自动分配数值,调试器可以在检查枚举变量时显示符号值,并且它们遵循块范围。 (当枚举被不加选择地混合时,编译器也可能生成非致命警告,因为这样做仍然可以被认为是坏风格,即使它不是严格违法的。)缺点是程序员几乎无法控制那些非致命警告;一些程序员也不喜欢无法控制枚举变量的大小。
答案 17 :(得分:0)
虽然上面的几个答案建议出于各种原因使用枚举,但我想指出使用定义在开发接口时具有实际优势。您可以引入新选项,并且可以让软件有条件地使用它们。
例如:
#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
在枚举时,如果没有运行时特征检测机制,这是不可能的。