在这篇文章的结尾处:http://www.learncpp.com/cpp-tutorial/45-enumerated-types/,它提到了以下内容:
最后,就像常量变量一样,枚举类型出现在调试器中,在这方面比#define的值更有用。
如何实现上述加粗的句子?
谢谢。
在这篇文章的结尾处:http://www.learncpp.com/cpp-tutorial/45-enumerated-types/,它提到了以下内容:
最后,就像常量变量一样,枚举类型出现在调试器中,在这方面比#define的值更有用。
如何实现上述加粗的句子?
谢谢。
考虑以下代码:
#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*
在错误消息中,您看不到您已经#defined
的宏WIDTH
,对吗?这是因为当GCC尝试编译与第二个错误对应的行时,它看不到WIDTH
,它只看到300,在GCC编译该行之前,预处理器已经用300替换了WIDTH
。另一方面,对于枚举eWidth
和常量Width
,没有发生任何这样的事情。
在此处查看错误:http://www.ideone.com/naZ3P
此外,请阅读Scott Meyers的《Effective C++》中Item 2: Prefer consts, enums, and inlines to #defines
。
#define X 40
)不占用任何内存。但是...请不要担心这个问题。即使const变量占用了一些字节,也请使用const
变量。在许多情况下,编译器可以优化代码,因此即使是const变量,也可以节省内存(如果它们确实是常量)。或者使用枚举,它们可以为您节省字节。 - Nawaz#define
的使用,但一直担心内存使用情况。 - RedXenum
应该可以帮助你在 C 中(或者在 C++ 中,你也可以使用 const
或 constexpr
定义的常量表达式)。试一试吧。 - Nawazenum
是编译时常量,具有调试信息但没有存储分配。
const
分配了一个存储位置,取决于编译器是否通过常量传播进行优化。
#define
没有存储分配。
#define
值会被预处理器替换为它们声明的值,因此在调试器中,只能看到值,而不是#defined名称。例如,如果您有 #define NUMBER_OF_CATS 10,在调试器中,你只会看到10(因为预处理器已经将代码中NUMBER_OF_CATS的每个实例替换为10)。
枚举类型是一种类型本身,其值是该类型的常量实例,因此预处理器不会对其进行更改,您将在调试器中看到该值的符号描述。
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
虽然我不认为这在所有架构上都可以实现。
至少对于我目前手头上的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
中设置了断点,你可以将鼠标悬停在"MyX"上,看到它的值为3。如果你将鼠标悬停在X上,则不会看到任何有用的信息。
但这并不是语言属性,而是IDE的行为。下一个版本可能会有所不同,其他IDE也可能如此。因此,请检查一下你的IDE,看看这个句子是否适用于你的情况。
X
(只有预处理后的值 3
),因此调试器绝对无法使用 X
作为符号名称,因此它将仅显示纯值 3
。这对所有编译器和 IDE 都是正确的。另一方面,在调试器中显示像 MyX
这样的符号确实是一个 IDE 特定的功能,但它是如此常见,我怀疑现代 IDE 中是否有任何不提供此功能的。 - Péter TörökX
放置在符号表中的方法。 - Pharap我回答得太晚了,但我觉得我可以补充一些内容 - 枚举 vs. 常量 vs. #define
枚举 -
您可以有一个枚举类型的变量,可以将枚举分配给该变量
typedef enum numbers { DFAULT, CASE_TRUE, CASE_OTHER, };
int main(void) { numbers number = CASE_TRUE; }
常量 -
定义是预处理指令,但const是编译时的 例如
const char *name = "vikas";
你可以访问变量名并使用其基地址,例如vikas [3]可读取'a'等。
#define - 是愚蠢的预处理器指令,只做文本替换。