C ++ – 枚举与常量与#define

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

最后,与常量variables一样,枚举types在debugging器中显示出来, 使得它们在这方面比#defined值更有用

上面的大胆的句子是如何实现的?

谢谢。

考虑这个代码,

#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:错误:'宽度* s'中'operator *'不匹配

在错误消息中,您没有看到#defined的macrosWIDTH ,对吧? 那是因为在GCC做任何编译行的尝试都是对应第二个错误的时候,看不到WIDTH ,它只能看到300,就像以前的GCC编译这行一样,预处理器已经WIDTHreplace成了300.另一方面手,没有任何这样的事情与枚举 eWidth常量 Width

请在这里查看错误: http : //www.ideone.com/naZ3P


此外,请阅读Scott Meyers的“ 有效C ++中Item 2 : Prefer consts, enums, and inlines to #defines

enum是编译时间不变的debugging信息,没有存储分配。

const被分配了一个存储空间,这取决于它是否被编译器通过不断的传播优化掉了。

#define没有存储分配。

#define值被预处理器replace为被声明的值,所以在debugging器中,它只能看到值,而不是#defined的名字,例如,如果你有#define NUMBER_OF_CATS 10,在debugging器中只能看10(因为预处理器已经用10代替了代码中NUMBER_OF_CATS的每个实例。

枚举types本身就是一个types,值是这种types的常量实例,所以预处理器将它独立出来,您将在debugging器中看到该值的符号描述。

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

当variables是枚举types时,debugging器可以显示枚举名称。 这是最好的例子:

 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) 

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

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

 xxd test | grep ONE_E 

不过,我认为这并不适用于所有架构。

至less对于我目前掌握的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,你可以将鼠标hover在“MyX”上,并且看到它的计算结果为3.如果你把鼠标hover在X上,你没有看到任何有用的东西。

但这不是一种语言属性,而是IDE行为。 下一个版本可能与其他IDE不同。 所以只要检查一下你的IDE,看看这句话是否适用于你的情况。

我回答得太晚,但我觉得我可以添加一些东西 – 枚举与常量与#定义

枚举

  1. 不需要确定值(如果只想要连续值0,1,2 …),而在#define的情况下,您需要手动pipe理可能导致人为错误的值
  2. 在线debugging期间,它的工作原理与variables一样,可以在监视窗口中观察enum的值
  3. 您可以有一个枚举types的variables,您可以分配一个枚举

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

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

const

  1. 它一直存储在内存的只读区,但是可以使用#define不可能的地址访问
    1. 如果您使用const而不是#define,则可以手持types检查
  2. 定义是预处理指令,但是const是编译时间

    const char * name =“vikas”;

您可以访问该名称并使用其基地址来读取诸如vikas [3]以读取“a”等

#定义 – 是愚蠢的预处理器指令,做文本replace

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