Thread: Case Statement

  1. #1
    Registered User
    Join Date
    Aug 2008
    Location
    Delaware
    Posts
    47

    Case Statement

    I'm working on an embedded controller, but my code space is limited.

    I have an Interrupt Routine that does a multitude of things, like increment software timers and set I/O states. It does these things based on a 4 bit variable.

    I have written a 15 state Case procedure to perform all these operations, but since many operations are duplicated, it is using excessive code space.

    Would I be better off using a nested If...else and parse the 4 bits? I am also concerned about execution time.

    Any other suggestions on how to accomplish this so it runs fast with the least code are welcome.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If the problem is with excessive usage of code space because of duplication of code then changing a switch into an if-else chain would not solve anything, methinks. More likely you would have to factor out the duplicate code into functions and call those functions... but then you incur a slight time penalty for each function call, but that may be acceptable.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Or use goto's? Labels are perfectly acceptable in Assembly, I don't see why they wouldn't in C.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Depends on the code.

    Perhaps something like this might be possible
    Code:
    switch ( var ) {
      case 1: case 3: case 5:
        // blah
        if ( var == 3 ) {
            // =3 specific
        }
        // blah
        break;
    Group nearly identical code into the same case, then use an if to isolate the minor differences.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    So you have 4 individual states, yes?

    If so, the if solution would be only 4 different if-statements, so it may be smaller - only way to really find out is to compile the two solutions (after validating that it's the same thing).

    Or you could have a hybrid solution, where you have a few switch-cases and if-statements in each case-label, e.g.
    Code:
        switch(x)
        {
           case 0:           
              // Some thing here. 
              break;
    
           case 1:
           case 2:
           case 3:
              if (x & 2) 
                 do stuff for case 2 & 3. 
              if (x & 1) 
                 do stuff common for 1 & 3
              if (x == 1) 
                 do stuff that is only for 1. 
              else
                 do stuff only for not 1. 
              break
          }

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Aug 2008
    Location
    Delaware
    Posts
    47
    I may use some kind of hybrid solution. Bits 0 and 1 are inter-dependant, and produce 3 states, while bits 2, and 3 are independant. I will try all the options, including a 3 case procedure for bits 0, and 1, and if...else for bits 3, and 4.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by danlee58 View Post
    I may use some kind of hybrid solution. Bits 0 and 1 are inter-dependant, and produce 3 states, while bits 2, and 3 are independant. I will try all the options, including a 3 case procedure for bits 0, and 1, and if...else for bits 3, and 4.
    bits 0 and 1 are interdependent, does this mean they can be treated / manipulated as a unit as this will reduce the 15 state Case procedure down to 8.
    how about a concrete example of how the bit patterns look like (interdependent and not).

  8. #8
    Registered User
    Join Date
    Aug 2008
    Location
    Delaware
    Posts
    47
    Here is a simplified version of what I have at this point. Bits 0 and 1 define three states, while bits 2, and 3 only define a single state each. I hope that I got the syntax right.

    Code:
    {
    int x;  //the 4 LSBs are the controling bits
    int VA, VB, VC, VD;
    
    if ((x & 0x3) !=0)
    {
       switch(x & 0x3)
    
               case 1:
             { 
            VA = 1000;
             }
             break:
              case 2:
             {
             VB = 500;
              }
             break:
             case 3:
             {
              VA = 900;
              VB = 400;
              }
     }
    
    if ((x & 0x4) !=0)
           {
            VC = 700;
            }
    if ((x & 0x8) !=0)
           {
            VD = 4000;
            }
    }
    Last edited by danlee58; 11-21-2008 at 03:15 PM.

  9. #9
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Perhaps bit-wise AND'ing with 0xF is all you need.
    Code:
    int x;
    int VA, VB, VC, VD;
    
    switch (x & 0xF)
    {
        case 1:
            VA = 1000;
            break;
        case 2:
            VB = 500;
            break;
        case 3:
            VA = 900;
            VB = 400;
            break;
        case 4:
            VC = 700;
            break;
        case 8:
            VD = 4000;
            break;
    }

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Just a mention: how about an array of function pointers? Mask off the 4 bits and jump to the function; some functions may be the same.

    [edit]Hopefully the compiler would optimize the switch in this fashion anyways, but YMMV. Also, since it's an ISR, I'd consider doing the above as an assembly jump table.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    Aug 2008
    Location
    Delaware
    Posts
    47
    You can't use a switch or a simple mask, since multiple bits may be set. You could have a 0x9 or even an oxf.

    The 0x9 requires case 1 and 8 to be executed. The 0xf requires that case 3 , 4, and 8 be executed.

    Either you define all cases 1 thru 15, or fall through a seiries of if ((x & mask) = ?), or some combination of the two.

    Cases 1 thru 15 creates a lot of code, while a series of ifs increases execution time.

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Just playing along at home with test code ... nothing to see here.
    Code:
    #include <stdio.h>
    
    void isr0(void) { fputs("isr0 ", stdout); }
    void isr1(void) { fputs("isr1 ", stdout); }
    void isr2(void) { fputs("isr2 ", stdout); }
    void isr3(void) { fputs("isr3 ", stdout); }
    void isr4(void) { fputs("isr4 ", stdout); }
    void isr5(void) { fputs("isr5 ", stdout); }
    void isr6(void) { fputs("isr6 ", stdout); }
    void isr7(void) { fputs("isr7 ", stdout); }
    void isr8(void) { fputs("isr8 ", stdout); }
    void isr9(void) { isr1(); isr8(); }
    void isrA(void) { fputs("isrA ", stdout); }
    void isrB(void) { fputs("isrB ", stdout); }
    void isrC(void) { fputs("isrC ", stdout); }
    void isrD(void) { fputs("isrD ", stdout); }
    void isrE(void) { fputs("isrE ", stdout); }
    void isrF(void) { isr3(); isr4(); isr8(); }
    
    void fakeisr(int value)
    {
       static void (*const function[])(void) =
       {
          isr0,isr1,isr2,isr3,isr4,isr5,isr6,isr7,
          isr8,isr9,isrA,isrB,isrC,isrD,isrE,isrF,
       };
       function[value & 0xF]();
       putchar('\n');
    }
    
    int main()
    {
       int i;
       for ( i = 0; i < 20; ++i )
       {
          printf("i = &#37;2d: ", i);
          fakeisr(i);
       }
       return 0;
    }
    
    /* my output
    i =  0: isr0
    i =  1: isr1
    i =  2: isr2
    i =  3: isr3
    i =  4: isr4
    i =  5: isr5
    i =  6: isr6
    i =  7: isr7
    i =  8: isr8
    i =  9: isr1 isr8
    i = 10: isrA
    i = 11: isrB
    i = 12: isrC
    i = 13: isrD
    i = 14: isrE
    i = 15: isr3 isr4 isr8
    i = 16: isr0
    i = 17: isr1
    i = 18: isr2
    i = 19: isr3
    */
    [edit]
    Code:
    #include <stdio.h>
    
    void isr0(void) {  }
    void isr1(void) { fputs("timers ", stdout); }
    void isr2(void) { fputs("I/O ", stdout); }
    void isr3(void) { isr2(); isr1(); }
    void isr4(void) { fputs("misc ", stdout); }
    void isr5(void) { isr4(); isr1(); }
    void isr6(void) { isr4(); isr2(); }
    void isr7(void) { isr4(); isr3(); }
    void isr8(void) { fputs("other ", stdout); }
    void isr9(void) { isr8(); isr1(); }
    void isrA(void) { isr8(); isr2(); }
    void isrB(void) { isr8(); isr3(); }
    void isrC(void) { isr8(); isr4(); }
    void isrD(void) { isr8(); isr5(); }
    void isrE(void) { isr8(); isr6(); }
    void isrF(void) { isr8(); isr7(); }
    
    void fakeisr(int value)
    {
       static void (*const function[])(void) =
       {
          isr0,isr1,isr2,isr3,isr4,isr5,isr6,isr7,
          isr8,isr9,isrA,isrB,isrC,isrD,isrE,isrF,
       };
       function[value & 0xF]();
       putchar('\n');
    }
    
    int main()
    {
       int i;
       for ( i = 0; i < 16; ++i )
       {
          printf("i = %2d: ", i);
          fakeisr(i);
       }
       return 0;
    }
    
    /* my output
    i =  0: 
    i =  1: timers 
    i =  2: I/O 
    i =  3: I/O timers 
    i =  4: misc 
    i =  5: misc timers 
    i =  6: misc I/O 
    i =  7: misc I/O timers 
    i =  8: other 
    i =  9: other timers 
    i = 10: other I/O 
    i = 11: other I/O timers 
    i = 12: other misc 
    i = 13: other misc timers 
    i = 14: other misc I/O 
    i = 15: other misc I/O timers 
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by danlee58 View Post
    You can't use a switch or a simple mask, since multiple bits may be set. You could have a 0x9 or even an oxf.

    The 0x9 requires case 1 and 8 to be executed. The 0xf requires that case 3 , 4, and 8 be executed.

    Either you define all cases 1 thru 15, or fall through a seiries of if ((x & mask) = ?), or some combination of the two.

    Cases 1 thru 15 creates a lot of code, while a series of ifs increases execution time.
    The switch statement is the better choice when you consider a series of else-if statements though its execution time should not increase drastically.
    What compiler and version are you using and perhaps gotos are the way to go for combinations like 0x9 or 0xf as in.
    Code:
    switch (c = x & 0xF)
        {
            case 1:
                one:
                    VA = 1000;
                    break;
            case 3:
                three:
                    VA = 900;
                    VB = 400;
                    break;
            case 4:
                four:
                    VC = 700;
                    if (c == 15)
                        goto three;
                    break;
            case 8:
               eight:
                    VD = 4000;
                    if (c == 9)
                        goto one;
                    else if (c == 15)
                        goto four;
                    break;
            case 9: case 15:
                goto eight;
        }
    }

  14. #14
    Registered User
    Join Date
    Aug 2008
    Location
    Delaware
    Posts
    47
    Quote Originally Posted by itCbitC View Post
    The switch statement is the better choice when you consider a series of else-if statements though its execution time should not increase drastically.
    What compiler and version are you using and perhaps gotos are the way to go for combinations like 0x9 or 0xf as in.
    Code:
    switch (c = x & 0xF)
        {
            case 1:
                one:
                    VA = 1000;
                    break;
            case 3:
                three:
                    VA = 900;
                    VB = 400;
                    break;
            case 4:
                four:
                    VC = 700;
                    if (c == 15)
                        goto three;
                    break;
            case 8:
               eight:
                    VD = 4000;
                    if (c == 9)
                        goto one;
                    else if (c == 15)
                        goto four;
                    break;
            case 9: case 15:
                goto eight;
        }
    }
    Something like that may be a little faster than a series of if statements. All 15 Cases would need to be defined, but 5 functions could be used to reduce redundant code. Case 15 would call function 8, 4 and 3 while case 14 would call function 8, 4, and 2. Case 13 would call function 8, 4, and 1 and so on.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Using case-labels more effectively removes one unnecessary goto:
    Code:
        case 9: 
        case 15:
        case 8:
    	VD = 4000;
    	if (c == 9)
    	    goto one;
    	else if (c == 15)
    	    goto four;
    	break;
    By rearranging the case-labels in opposite order and using fall-through, we can remove all remaining gotos:
    Code:
    void func2(int x)
    {
        int c, d;
        c = x & 0x0f;
        d = c & 3;
        switch(c)
        {
        case 15:
        case 9:
        case 8:
    	VD = 4000;
        case 4:
    	if (c & 4)
    	    VC = 700;
        case 3:
        case 1:
    	if (d == 1)
    	{
    	    VA = 1000;
    	}
    	else if (d == 3)
    	{
    	    VA = 900;
    	    VB = 400;
    	}
        }
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 03-05-2009, 11:32 AM
  2. switch case statement
    By stanlvw in forum C++ Programming
    Replies: 3
    Last Post: 02-26-2008, 05:06 AM
  3. Intel syntax on MinGW ?
    By TmX in forum Tech Board
    Replies: 2
    Last Post: 01-06-2007, 09:44 AM
  4. char copy
    By variable in forum C Programming
    Replies: 8
    Last Post: 02-06-2005, 10:18 PM
  5. Strings and Switch Statement
    By Ajsan in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2004, 01:16 PM