Function pointer question

Started by
12 comments, last by eighty 19 years, 8 months ago
Hi, I'm writing a little program targetting a microcontroller. It's somewhat a state machine, where the program is always looping throw a defined state until it founds that some condition changed and hence must go to a new state. These states are implemented as individual functions:

char stateA() {
  for(;;) {
    if(condition1) {
      //do something
      return 'B';  //go to state B
    }
    else if(condition2) {
      //do something else
      return 'D';  //go to state B
    }
  }
}
The main function initially sets the state and then enters an infinete loop switching between states:

main() {
  char state = 'A';
  for(;;) {
    switch(state) {
      case 'A':
        state = stateA();
        break;
      case 'B':
        state = stateB();
        break;
      case 'C':
        state = stateB();
        break;
      case 'D':
        state = stateD();
        break;
    }
  }
}
This is working find, but it's not very comfortable to add new states because I need to touch a lot of code (the program is big, I have enums, constants, #defines, etc) So I think a nicer approach would be to make the states functions return a pointer to another state function instead of a char. The problem is I don't know how to declare such a pointer (I don't know if it is even possible) since the type of the function pointed to is the same as the type being defined. Can anyone tell me how can I do this, it is at all possible ? Thanks a lot
Advertisement
I suppose you could return void* and cast the result back to a function when you want to use it, but a neater solution would probably be to use functors inheriting from an abstract base class State.
Quote:Original post by eighty
I suppose you could return void* and cast the result back to a function when you want to use it, but a neater solution would probably be to use functors inheriting from an abstract base class State.


We don't even know if he might be using strick C here this is for a micro-controller, anyways if you are using C and not C++ first this web-site will tell all you need to know about function pointers here. And here is a little program that shows you how to return a the address of some function in strict C and you don't need to use a void pointer for this:

#include <stddef.h>#include <stdio.h>void func1() {  printf("hello func1\n");  }void func2() {   printf("hello func2\n");}typedef void (*state_func)();state_func state(size_t i) {      static const state_func array_of_funcs[] = { func1, func2 };   return array_of_funcs;}int main() {      state_func f = state(0);   (*f)();   f = state(1);   (*f)();   return 0;}


[Edited by - snk_kid on August 3, 2004 6:57:32 AM]
if you're using plain C this will work
#include <stdio.h>#include <conio.h>typedef void* (state_t)(void);state_t init_state, run_state, exit_state;void* init_state(void){	puts("Hello and welcome!");	return run_state;}void* run_state(void){	do	{		puts("press 'q' to quit.");	}while(getch() != 'q');	return exit_state;}void* exit_state(void){	puts("doing cleanup");	return NULL;}int main(void){	state_t *state = init_state;	while( state) state = state();}


if you're using C++ you either have to do some casting or use functors or some other technique, it basicly boils down to what language you're using.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
See StatePattern (and StrategyPattern).

Also, there is an implementation of a FSM using templates in boost's meta programming language library
Also see Robert Martin's State Machine Compiler and the similarly named smc on sourceforge
OK, thanks a lot for those replies.

I forgot to mention I'm using an almost-ANSI C compiler (it doesn't support recursive calls and some other few features).

I will try the void* thing first, but I guess it won't work, since it is a Harvard arquitecture microcontroller.

Thanks again
I think I miaght have found a solution. Let me know what you think about it.

struct statetag;typedef struct statetag(*state_func)();typedef struct statetag {	state_func execute;}state_t;state_t stateA();state_t stateB();state_t stateC();int main(int argc, char *argv[]) {	state_t curstate;	curstate.execute = stateA;	for(;;) {		curstate = curstate.execute();	}   getchar();   return 0;}state_t stateA() {	char c;	state_t s;	printf("State A\n");	for(;;) {		c = getch();		switch(c) {			case 'b': s.execute = stateB; break;			case 'c': s.execute = stateC; break;		}		return s;	}}state_t stateB() {	char c;	state_t s;	printf("State B\n");	for(;;) {		c = getch();		switch(c) {			case 'a': s.execute = stateA; break;			case 'c': s.execute = stateC; break;		}		return s;	}}state_t stateC() {	char c;	state_t s;	printf("State C\n");	for(;;) {		c = getch();		switch(c) {			case 'a': s.execute = stateA; break;			case 'b': s.execute = stateB; break;		}		return s;	}}
Quote:Original post by eighty
I suppose you could return void* and cast the result back to a function when you want to use it, but a neater solution would probably be to use functors inheriting from an abstract base class State.


I had always assumed that "functor" was short for function pointer, but apparently that is not the case. So what exactly is a functor then?
A functor is a class whose function operator (operator ()) has been overridden.

Example:
class Printer{public:   void operator () (const char *s)   {     cout << "I can print, says " << s << endl;   }};Printer p;p ("Stoffel"); // prints "I can print, says Stoffel"


Not a very exciting functor, but one nonetheless. Note the second void (the one in the argument list) is unnecessary, but that's where you'd put arguments. The return type can also be anything you want. You can treat the class objects like functions.

This topic is closed to new replies.

Advertisement