C ++ - enum vs. const vs. #define

时间:2011-01-22 11:55:44

标签: c++ macros constants enumeration

在这篇文章的最后:http://www.learncpp.com/cpp-tutorial/45-enumerated-types/,它提到了以下内容:

最后,与常量变量一样,枚举类型显示在调试器中,使它们在这方面比#defined值更有用

上面的粗体句子是如何实现的?

感谢。

7 个答案:

答案 0 :(得分:29)

考虑这段代码,

#define WIDTH 300

enum econst
{
   eWidth=300
};

const int Width=300;

struct sample{};

int main() 
{
        sample s;
        int x = eWidth * s; //error 1
        int y = WIDTH * s;  //error 2
        int z = Width * s;  //error 3
        return 0;
}

显然,每次乘法都会导致编译错误,但是看看GCC如何为每个乘法错误生成消息:

  

prog.cpp:19:错误:不匹配   'eWidth * s'中的'operator *'   prog.cpp:20:错误:不匹配   '300 * s'中的'operator *'   prog.cpp:21:错误:不匹配   'Width * s'中的'operator *'

在错误消息中,您没有看到WIDTH的宏#defined,对吧?这是因为当GCC使编译该行的任何尝试都对应于第二个错误时,它看不到WIDTH,它只看到300,就像之前GCC编译该行一样,预处理器已经已经< / strong>用300替换WIDTH。另一方面, enum eWidth const {{1}没有任何此类事情发生}}

请在此处查看错误:http://www.ideone.com/naZ3P


此外,请阅读Scott Meyers的 Effective C ++ 中的Width

答案 1 :(得分:14)

enum是编译时间常量,带有调试信息,没有存储分配。

const分配了一个存储,具体取决于编译器是否通过常量传播对其进行了优化。

#define没有存储空间分配。

答案 2 :(得分:6)

#define值被预处理器替换为它们被声明为的值,因此在调试器中,它只能看到值,而不是#defined名称,例如如果您有#define NUMBER_OF_CATS 10,则在调试器中您只会看到10个(因为预处理器已将代码中的每个NUMBER_OF_CATS个实例替换为10个。

枚举类型本身就是一个类型,值是这种类型的常量实例,因此预处理器将其单独放置,您将在调试器中看到该值的符号描述。

答案 3 :(得分:3)

当使用某些选项编译程序时,编译器将枚举信息存储在二进制文件中。

当变量是枚举类型时,调试器可以显示枚举名称。最好用一个例子显示:

enum E {
    ONE_E = 1,
};

int main(void)
{
    enum E e = 1;

    return 0;
}

如果您使用gcc -g进行编译,可以在gdb中试用以下内容:

Reading symbols from test...done.
(gdb) b main
Breakpoint 1 at 0x804839a: file test.c, line 8.
(gdb) run
Starting program: test 

Breakpoint 1, main () at test.c:7
7               enum E e = 1;
(gdb) next
9               return 0;
(gdb) print e
$1 = ONE_E
(gdb) 

如果你使用了一个定义,你将没有一个合适的类型来提供e,并且必须使用一个整数。在这种情况下,编译器将打印1而不是ONE_E

-g标志要求gdb将调试信息添加到二进制文件中。你甚至可以通过发出:

来看到它在那里
xxd test | grep ONE_E

但我认为这不适用于所有架构。

答案 4 :(得分:0)

至少对于我目前手边的Visual Studio 2008,这句话是正确的。如果你有

#define X 3
enum MyEnum
{
    MyX = 3
};

int main(int argc, char* argv[])
{
    int i = X;
    int j = (int)MyX;
    return 0;
}

并且您在main设置了一个breakpont,您可以将鼠标悬停在“MyX”上,并看到它的评估结果为3.如果将鼠标悬停在X上,则看不到任何有用的内容。

但这不是语言属性,而是IDE行为。下一版本可能会以不同的方式执行,以及其他IDE。因此,只需检查一下您的IDE,看看这句话是否适用于您的情况。

答案 5 :(得分:0)

我回答太晚但我觉得我可以添加一些东西 - enum vs. const vs. #define

枚举 -

  1. 不需要约束值(如果只想要序列值为0,1,2 ......),而在#defines的情况下,您需要手动管理可能导致人为错误的值
  2. 在线调试期间,它可以作为变量使用,可以在监视窗口中观看枚举的值
  3. 您可以使用枚举类型的变量来指定枚举

    typedef枚举数字 {   DFAULT,   CASE_TRUE,   CASE_OTHER, };

    int main(void) {   numbers number = CASE_TRUE; }

  4. const -

    1. 它是常量存储在内存的只读区域,但可以使用#define无法访问的地址访问
      1. 如果您使用const而不是#define
      2. ,那么您手中会进行类型检查
    2. 定义是预处理指令,但const是编译时 例如

      const char * name =“vikas”;

    3. 您可以访问该名称并使用其基地址来阅读诸如vikas [3]以阅读'a'等。

      #defines - 是愚蠢的预处理程序指令,它进行文本替换

答案 6 :(得分:0)

检查以下文章,很好的总结 http://www.queryhome.com/26340/define-vs-enum-vs-constant