开发者

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

At the end of the article here: http://www.learncpp.com/cpp-tutorial/45-enumerated-types/, it mentions the following:

Finally, as with constant variables, enumerated types show up in the debugger, making them more useful than #defined values in t开发者_C百科his regard.

How is the bold sentence above achieved?

Thanks.


Consider this code,

#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;
}

Obviously each multiplication results in compilation-error, but see how the GCC generates the messages for each multiplication error:

prog.cpp:19: error: no match for ‘operator*’ in ‘eWidth * s’
prog.cpp:20: error: no match for ‘operator*’ in ‘300 * s’
prog.cpp:21: error: no match for ‘operator*’ in ‘Width * s’

In the error message, you don't see the macro WIDTH which you've #defined, right? That is because by the time GCC makes any attempt to compile the line corresponds to second error, it doesn't see WIDTH, all it sees only 300, as before GCC compiles the line, preprocessor has already replaced WIDTH with 300. On the other hand, there is no any such thing happens with enum eWidth and const Width.

See the error yourself here : http://www.ideone.com/naZ3P


Also, read Item 2 : Prefer consts, enums, and inlines to #defines from Effective C++ by Scott Meyers.


enum is compile time constant with debug info with no storage allocation.

const is allocated with a storage, depending on whether it is optimised away by the compiler with constant propagation.

#define has no storage allocation.


#define values are replaced by the pre-processor with the value they are declared as, so in the debugger, it only sees the value, not the #defined name, e.g. if you have #define NUMBER_OF_CATS 10, in the debugger you'll see only 10 (since the pre-processor has replaced every instance of NUMBER_OF_CATS in your code with 10.

An enumerated type is a type in itself and the values are constant instances of this type, and so the pre-processor leaves it alone and you'll see the symbolic description of the value in the debugger.


The compiler stores enum information in the binary when the program is compiled with certain options.

When a variable is of a enum type, a debugger can show the enum name. This is best shown with an example:

enum E {
    ONE_E = 1,
};

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

    return 0;
}

If you compile that with gcc -g you can try out the following in 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) 

If you used a define, you would not have a proper type to give e, and would have to use an integer. In that case, the compiler would print 1 instead of ONE_E.

The -g flag asks gdb to add debugging information to the binary. You can even see that it is there by issuing:

xxd test | grep ONE_E

I don't think that this will work in all architectures, though.


At least for Visual Studio 2008 which I currently have at hand, this sentence is correct. If you have

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

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

and you set a breakpont in main, you can hover your mouse over "MyX" and see that it evaluates to 3. You do not see anything useful if you hover over X.

But this is not a language property but rather IDE behavior. Next versions might do it differently, as well as others IDEs. So just check it out for your IDE to see if this sentence applies in your case.


I am answering too late but i feel i can add something - enum vs. const vs. #define

enum -

  1. Does not require assining values (if just want to have sequential values 0, 1, 2..) whereas in case of #defines you manually need to manage values which could cause human error sometime
  2. It works just as variable to during online debugging the value of enum can be watched in watch window
  3. You can have a variable of enum type to which you can assign an enum

    typedef enum numbers { DFAULT, CASE_TRUE, CASE_OTHER, };

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

const -

  1. It is constant stored in read only area of memory but can be accessed using address which is not possible in case of #define
    1. You have type check in your hand if you use const rather than #define
  2. defines are pre-processing directive but const is compile time for example

    const char *name = "vikas";

You can access the name and use its base address to read the such as vikas[3] to read 'a' etc.

#defines - are dumb preprocessor directives which does textual replacement


Check the following article, nice summary http://www.queryhome.com/26340/define-vs-enum-vs-constant

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜