zangw
zangw

Reputation: 48356

How to replace preprocessor macro with if statement?

Usually, the preprocessor macro is used to control some code group to be compiled or not. Here is one example.

#define ENABLE 1

void testswitch(int type){

    switch(type){
    case 1:
        std::cout << "the value is 1" << endl;
        break;
    case 2:
        std::cout << "the value is 2" << endl;
        break;
#ifdef ENABLE
    case 3:
        std::cout << "the value is 3" << endl;
        break;
    case 4:
        std::cout << "the value is 4" << endl;
    }
#endif
    }
}

Now I want to remove all those preprocessor macros and replace them with if condition

void testswitch(int type, bool enable){
    switch(type){
    case 1:
        std::cout << "the value is 1" << endl;
        break;
    case 2:
        std::cout << "the value is 2" << endl;
        break;
    if (enable) {
    case 3:
        std::cout << "the value is 3" << endl;
        break;
    case 4:
        std::cout << "the value is 4" << endl;
    }
    }
}

However, the above codes doesn't have the same logic as before. No matter the variable enable is true or false, the case 3 and case 4 are always enable. Those codes are test under VS2010.

Q1: Does the compiler ignore the if condition?

To achieve my goal, I have to change those codes as following:

void testswitch(int type, bool enable){
    switch(type){
    case 1:
        std::cout << "the value is 1" << endl;
        break;
    case 2:
        std::cout << "the value is 2" << endl;
        break;
    case 3:
        if (enable) 
            std::cout << "the value is 3" << endl;
        break;
    case 4:
        if (enable) 
            std::cout << "the value is 4" << endl;
    }
}

But it seems there are redundant if in the codes. Is there any better way to do that?

Upvotes: 2

Views: 673

Answers (3)

The compiler does not ignore the if condition. But you have to bear in mind that the case labels are labels. switch is just a more organised approach to goto. Since goto can jump into blocks controlled by an if (or a loop, or any others) just fine, so can a switch.

You could put the enable-only cases in a separate switch:

void testswitch(int type, bool enable) {
  switch(type) {
  case 1:
    std::cout << "the value is 1" << endl;
    break;
  case 2:
    std::cout << "the value is 2" << endl;
    break;
  default:
    if (enable) {
      switch(type) {
      case 3:
        std::cout << "the value is 3" << endl;
        break;
      case 4:
        std::cout << "the value is 4" << endl;
        break;
      }
    }
    break;
  }
}

Upvotes: 2

Paul R
Paul R

Reputation: 212929

One other solution is to refactor this into two switch statements, with the second one being controlled by if (enable):

void testswitch(int type, bool enable) {
    switch(type) {
        case 1:
            std::cout << "the value is 1" << endl;
            break;
        case 2:
            std::cout << "the value is 2" << endl;
            break;
        default:
            break;
    }
    if (enable) {
        switch(type) {
            case 3:
                std::cout << "the value is 3" << endl;
                break;
            case 4:
                std::cout << "the value is 4" << endl;
                break;
            default:
                break;
        }
    }
}

Upvotes: 1

Dwayne Towell
Dwayne Towell

Reputation: 8583

If enable is a constant (or otherwise known at compile-time), a reasonably smart compiler (like gcc) will not generate code to check the value of enable, but will generate no code (if it is known to be false) or generate the then-statement otherwise.

Upvotes: 0

Related Questions