为什么使用 #define 而不是枚举?

15 浏览
0 Comments

为什么使用 #define 而不是枚举?

在C语言中,下面的语句中哪一个更好用?

static const int var = 5;

还是

#define var 5

还是

enum { var = 5 };

0
0 Comments

在C语言中,使用#define(或者如果合适的话,使用enum)比使用const更好的原因是,虽然具有const对象的作用域和类型属性是有益的,但实际上,在C语言中,const对象(与C++不同)不是真正的常量,因此在大多数实际情况下通常是无用的。

因此,在C语言中,选择应该根据您计划如何使用常量来决定。例如,您不能将const int对象用作case标签(而宏将起作用)。您不能将const int对象用作位字段宽度(而宏将起作用)。在C89/90中,您不能使用const对象指定数组大小(而宏将起作用)。即使在C99中,当您需要一个非VLA(可变长度数组)数组时,也不能使用const对象指定数组大小。

如果这对您很重要,那么它将决定您的选择。大多数情况下,您只能在C语言中使用#define。不要忘记另一种可在C语言中生成真正常量的选择 - enum。

在C++中,const对象是真正的常量,因此在C++中通常更好地使用const变体(在C++中不需要显式的static)。

在对“您不能将const int对象用作case标签(而宏将起作用)”这个观点表示怀疑时,我在C语言中使用了一个const int变量来测试switch-case,它可以工作...

0
0 Comments

为什么使用#define而不是枚举?

在代码中定义常量时,我们通常使用#define或枚举。然而,为什么一些情况下我们更倾向于使用#define而不是枚举呢?

下面的讨论给出了这个问题的原因和解决方法。

首先,我们需要考虑我们需要这个值的用途。下面是三种定义常量的方法:

1. static const int var = 5;

2. #define var 5

3. enum { var = 5 };

那么为什么有时候我们更倾向于使用#define呢?

1. 如果我们需要传递一个指针,我们必须使用第一种方法(static const int)。

2. 如果第二种方法(#define)是可选的,那么我们不需要传递指针。

3. 第一种和第三种方法在调试器的符号表中有一个符号,这样调试会更容易。而第二种方法可能没有符号,让你不知道它是什么。

4. 第一种方法(static const int)不能用作全局作用域的数组维度,而第二种(#define)和第三种(enum)都可以。

5. 第一种方法(static const int)不能用作函数作用域的静态数组的维度,而第二种(#define)和第三种(enum)都可以。

6. 在C99中,这些方法都可以用于局部数组。使用第一种方法会暗示使用VLA(可变长度数组),尽管'var'引用的维度大小当然是固定的,为5。

7. 第一种方法(static const int)不能用在switch语句等地方,而第二种(#define)和第三种(enum)都可以。

8. 第一种方法(static const int)不能用来初始化静态变量,而第二种(#define)和第三种(enum)都可以。

9. 第二种方法(#define)可能会改变你不想改变的代码,因为它被预处理器使用;而第一种方法(static const int)和第三种方法(enum)不会有意外的副作用。

10. 你可以检测预处理器是否设置了第二种方法(#define),而第一种(static const int)和第三种(enum)都不允许这样做。

所以,在大多数情况下,我们更倾向于使用枚举(enum)。否则,第一种方法(static const int)和最后一点很可能是决定因素,如果你需要同时满足这两个条件,你需要更深入地思考。

如果你问的是关于C++的话,那么你应该每次都使用第一种方法(static const int)。

总之,根据我们需要的功能,我们可以选择使用#define或枚举来定义常量。每种方法都有自己的优点和适用场景。

0
0 Comments

为什么使用#define而不是枚举?

使用#define而不是枚举的原因是它尊重作用域并且是类型安全的。这是一个普遍适用的原则。

然而,如果你希望变量可能在命令行上定义,那就有一个替代方案。可以使用#ifdef来检查变量是否已经定义,然后根据情况分别定义变量。这样可以在命令行上定义变量的值。

在可能的情况下,尽量避免使用宏和省略号,而是使用类型安全的替代方法。

如果你真的需要使用宏(例如,你想要使用__FILE__或__LINE__),那么最好给宏起一个非常谨慎的名字。Boost在其命名约定中建议使用全部大写的名字,并以项目名称开头,然后跟着特定区域(库)的名称,最后是有意义的名字。这通常会导致较长的名字。

某些情况下,使用#define会导致代码混乱,因为预处理器不了解语法。因此,最好使用#if而不是#ifdef。另外,CCAN已经将这个作为他们的风格指南的一部分。

这是一个标准的C++宣传。下面的答案更清楚地解释了选项的真正含义。特别是:我刚刚遇到了一个问题,"static const"被用来在一个头文件中定义大约2000个"常量"。然后这个头文件被包含在大约100个".c"和".cpp"文件中。结果就是"consts"占用了8M字节的空间。是的,我知道你可以使用链接器来删除未引用的常量,但是这仍然会导致你仍然有一些被引用的"consts"。这个答案有什么问题。

对于一个好的编译器来说,只有那些取地址的静态变量才会保留下来;而且如果取了地址,就不能使用#define或者enum(没有地址)……所以我真的看不出还有其他什么选择。如果可以放弃"编译时评估",那么可能你要找的是extern const。

某些情况下使用#define CONST_VALUE ((int)5)。如果我想要一个常量值,如果不能取地址,这是一个优势。如果我想要简单的整数常量值,我不想要它们的地址。

至于static constexpr呢?它不应该完全像static const一样吗?

对于整数而言,它们应该没有区别。constexpr和const的区别在于何时计算值。constexpr保证在编译时计算值(因此在main函数开始之前不会执行任何函数),这也保证了该值将可供优化器使用……然而请注意,这是一个C的问题,C中没有constexpr。

这是一个关于C的问题,而不是C++。在C中,const表示只读,而不是常量。你可以在块内声明一个const,获取一个指向它的指针,并修改它的值。

在c99的内联函数中,你不能引用静态变量,所以在这种情况下你仍然必须使用#define。

可以去掉static,使用匿名命名空间。namespace { const int var = 123; }。

那么,如果我希望全局const在任何地方都可用呢?

0