Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C programming lookup table

After some help as have some code which works but trying to fully understand a small section which uses a lookup table as part of a state machine. The state machine I understand and have been using for a tutorial I am writing found here http://coder-tronics.com/state-machine-tutorial-pt1 Instead of using more switch case statements inside the UponExit, UponEnter and ActionWhileInState, someone suggested using this method which I like but don't fully understand.

Now the part I am unsure about is these lines to do with the typedef and lookup table

typedef void (* const voidFunc)(void);

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

I looked up typedef and lookup tables and have a basic understanding, but was hoping someone could give a brief walk through of how this works in this case?

The full part of code this relates to is below for completeness.

enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
enum events { E_OFF, E_ON, E_START, E_MAX};
typedef void (* const voidFunc)(void);
void hEnter_OFF(void);   void hEnter_ON(void);   void hEnter_PROCESS(void);
void hInState_OFF(void); void hInState_ON(void); void hInState_PROCESS(void);
void hExit_OFF(void);    void hExit_ON(void);    void hExit_PROCESS(void);

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

enum states StateMachine(enum events event, enum states Current_State)
{
    int Next_State = Current_State;

    switch ( Current_State )
    {
            case S_OFF:
       switch (event )
       {
           // A transition to the next state will occur here
           case E_ON:
            Next_State = S_ON;
               break;
           default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
               break;   //to handle all enumerated values
       }
       break;
   case S_ON:
       switch (event )
       {
           // A transition to the next state will occur here
           case E_OFF:
            Next_State = S_OFF;
               break;
           case E_START:
            Next_State = S_PROCESS;
               break;
           default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
               break;   //to handle all enumerated values
       }
       break;
   case S_PROCESS:
       switch (event )
       {
           // A transition to the next state will occur here
       case E_OFF:
        Next_State = S_OFF;
           break;
       default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
           break;   //to handle all enumerated values
       }
       break;
       // The program should never arrive here
    default:
       break;
    }

    if (Next_State != Current_State)
    {
        // Function call for Upon Exit function, it can be omitted but allows extra functionality
        UponExit[Current_State]();
        // Function call for Upon Enter function, it can be omitted but allows extra functionality
        if (Next_State != S_MAX) UponEnter[Next_State]();
    }
    else // I think ActionWhileInState should only be called when NOT doing a transition!
     {
        if ( event != E_MAX) ActionWhileInState[Current_State]();
    }
    return Next_State;
}

Thanks,

Ant

like image 305
Ant Avatar asked Dec 12 '25 03:12

Ant


1 Answers

typedef void (* const voidFunc)(void);

is a typedef for a function pointer (for a pointer to a function expecting no parameters and not returning anything to be exact). So your arrays

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS}; 
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

Each hold three different function pointers, one for each state. So a line like

UponExit[Current_State]();

calls the function the pointer UponExit[Current_State] points to which is hExit_OFF if Current_State is 0, hExit_ON if Current_State is 1 or hExit_PROCESS if Current_State is 2. You could also write the line like that:

(*UponExit[Current_State])();

What looks more complicated but makes clear that UponExit[Current_State] is a function pointer that is "dereferenced" to a call to the function it points to.

Edit:

You have an enum for your states:

enum states { S_OFF, S_ON, S_PROCESS, S_MAX };

Thus, S_OFF == 0, S_ON == 1, S_PROCESS == 2 and S_MAX == 3 (look here)

like image 193
Ingo Leonhardt Avatar answered Dec 14 '25 19:12

Ingo Leonhardt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!