Why does the C preprocessor consider enum values as equal?

Gnubie picture Gnubie · Jan 8, 2016 · Viewed 10.6k times · Source

Why does the std::cout line in the following code run even though A and B are different?

#include <iostream>

enum T { A = 1, B = 2 };
// #define A 1
// #define B 2

int main() {
#if (A == B)
    std::cout << A << B;
#endif
}

If I use #define instead (as commented out), I get no output as I expect.

Reason for the question:

I want to have a mode selector for some test code in which I can easily change modes by commenting/uncommenting lines on top:

enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
// #define MODE MODE_RGB
#define MODE MODE_GREY
// #define MODE MODE_CMYK

int main() {
#if (MODE == MODE_RGB)
    // do RGB stuff
#elif (MODE == MODE_GREY)
    // do greyscale stuff
#else
    // do CMYK stuff
#endif

    // some common code

    some_function(arg1, arg2,
#if (MODE == MODE_RGB)
        // RGB calculation for arg3,
#elif (MODE == MODE_GREY)
        // greyscale calculation for arg3,
#else
        // CMYK calculation for arg3,
#endif
        arg4, arg5);
}

I know I can use numeric values e.g.

#define MODE 1 // RGB
...
#if (MODE == 1) // RGB

but it makes the code less readable.

Is there an elegant solution for this?

Answer

Simple picture Simple · Jan 8, 2016

There are no macros called A or B, so on your #if line, A and B get replaced by 0, so you actually have:

enum T { A = 1, B = 2 };

int main() {
#if (0 == 0)
    std::cout << A << B;
#endif
}

The preprocessor runs before the compiler knows anything about your enum. The preprocessor only knows about macros (#define).