Home > Net >  C Macro expanding in ordinal numbers
C Macro expanding in ordinal numbers

Time:01-30

I have a code that compiles on various platforms having different features on or off (each represented by a specific define) and I am scratching my head on how to do the following switch (int) statement that would keep "case (number):" ordered and continuous.

int funcParam;
switch(funcParam)
{
case 0: break;

case 1:break;

#ifdef FEATURE_1
case 2: break;
#endif // FEATURE_1

case 3: break;  // <<== problem here: 3 follows 1 if FEATURE_1 is not defined

#ifdef FEATURE_2
case 4: break; <<== problem here: 4 follows 2 if FEATURE_1 is not defined
#endif // FEATURE_2

#ifdef FEATURE_3
case 5: break; <<== problem here: 5 follows 2 or 3 or 4 depending on features
#endif // FEATURE_3
}

Each case block of code is a block of 10 or so lines, I guess this is irrelevant, however the perfect solution to have would be to find a way to emit code like:

case NEXTNUM:

that would expand to a next ordinal number with each expansion of a macro NEXTNUM. Not having an idea on how could it possibly be written.

Please keep in mind that I am using quite old compiler (C 98, may consider C 03).

Thanks, Radek

CodePudding user response:

instead of case 0, case 1… and so on, use values from an enum; these are also compile-time constants, and thus, legal as case values.

You can insert the same #ifdef feature checks into the enum definition, then the enum options are still continuously labeled.

Rule of thumb though:

  1. you're not making anything prettier that way. Honestly, having a feature enabled or not should probably not change the values functions exchange – that's just ugly and a recipe for debugging disaster. So, I question your motivation!
  2. a case costs nearly nothing. Instead or removing these cases, you should probably think about what the right operation is when that case is triggered. A warning? A system shutdown?
  3. The fact that you're not using an enum in switch/case is a really um, bad sign, and you relying on cases still being contiguously numbered is actively worrying. Using magic numerical constants is bad enough style on its own – making them have different meanings on different feature sets screams "architectural mistakes have been made". I'd duly replace all my magic numeric values with entries from an enum. You will be happier afterwards.

Lastly: uff. C 98. C 03 is 20 years old. It's an important bug-fix release that basically broke nothing. You really should not hesitate a second to use it.

CodePudding user response:

Create variables equal 0 and 1 depending on if the feature is enabled. Add these variables to cases after the feature case.

int main() {
    int funcParam;
    const int add_feature_1 = 
#ifdef FEATURE_1
        1
#else
        0
#endif
        ;
    const int add_feature_2 = 
#ifdef FEATURE_2
        1
#else
        0
#endif
        ;
    const int add_feature_3 = 
#ifdef FEATURE_3
        1
#else
        0
#endif
        ;
    switch(funcParam) {
    case 0: break;
    case 1: break;
#ifdef FEATURE_1
    case 2: break;
#endif
    case 2   add_feature_1: break;
#ifdef FEATURE_2
    case 3   add_feature_1: break;
#endif // FEATURE_2
#ifdef FEATURE_3
    case 3   add_feature_1   add_feature_2: break;
#endif // FEATURE_3
    }
}

Consider refactoring your code, so that FEATURE_X has to be defined (which I consider better) and instead define FEATURE_X to number 0 or 1. Then you could:

#define FEATURE_1 0
#define FEATURE_2 1
#define FEATURE_3 0
int main() {
    int funcParam;
    switch(funcParam) {
    case 0: break;
    case 1: break;
#if FEATURE_1
    case 2: break;
#endif
    case 2   FEATURE_1: break;
#if FEATURE_2
    case 3   FEATURE_1: break;
#endif // FEATURE_2
#if FEATURE_3
    case 3   FEATURE_1   FEATURE_2: break;
#endif // FEATURE_3
    }
}

Or similar combinations, you should get the idea.

  • Related