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编译这行一样,预处理器已经把WIDTH
replace成了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,看看这句话是否适用于你的情况。
我回答得太晚,但我觉得我可以添加一些东西 – 枚举与常量与#定义
枚举 –
- 不需要确定值(如果只想要连续值0,1,2 …),而在#define的情况下,您需要手动pipe理可能导致人为错误的值
- 在线debugging期间,它的工作原理与variables一样,可以在监视窗口中观察enum的值
-
您可以有一个枚举types的variables,您可以分配一个枚举
typedef枚举数{DFAULT,CASE_TRUE,CASE_OTHER,};
int main(void){numbers number = CASE_TRUE; }
const –
- 它一直存储在内存的只读区,但是可以使用#define不可能的地址访问
- 如果您使用const而不是#define,则可以手持types检查
-
定义是预处理指令,但是const是编译时间
const char * name =“vikas”;
您可以访问该名称并使用其基地址来读取诸如vikas [3]以读取“a”等
#定义 – 是愚蠢的预处理器指令,做文本replace