带函数指针的状态机:如何设置函数指针?

Posted

技术标签:

【中文标题】带函数指针的状态机:如何设置函数指针?【英文标题】:State machines with function pointers: how to set the function pointers? 【发布时间】:2012-12-13 16:23:19 【问题描述】:

This question 询问有 100 个状态且每个状态有 100 个事件的有限状态机,然后对使用 if-elseswitch 语句或函数指针来实现状态机进行简要比较。

我的问题是:如果使用函数指针,如何正确设置函数指针?使用if-elseswitch 语句(在这种情况下,函数指针是否更像是一种混合解决方案)?还是有其他常用的方法?

【问题讨论】:

【参考方案1】:

我希望每个状态都由一个函数表示,并且所有状态都可以“了解”彼此。

所以,设置可以是直接的:

void set_state(void (*state)(void))

  the_current_state = state;


void state_idle(void)

  printf("oh, hai, boring to be in the idle state, let's switch\n");
  set_state(state_busy);

这假定当前状态由全局函数指针 (the_current_state) 建模。

您当然也可以让每个状态返回新状态,或者NULL 表示“不要切换”。

【讨论】:

【参考方案2】:

您可以执行以下操作:

typedef int (*current_state) (void);
typedef int (*nextnew_state) (void);
struct FuncPointerState

  current_state curr_state;
  nextnew_state next_state;
; 


/*init_state is the initial function state*/
struct FuncPointerState FpState = init_state, NULL;     
int iRet = 0;

while(1)


   iRet = FpState.curr_state();
   if(iRet<= 0 )
   
      return iRet;
   
   if(NULL==FpState.next_state)
   
     /* State Machine finished it's job */
      break;
   
   FpState.curr_state = FpState.next_state;


每个状态函数都应该填充 next_state 指针。此外,您可以修改函数指针以获取输入参数。

【讨论】:

【参考方案3】:
struct state_fn 
   void (*handler)(void);
;

static int state;
static struct state_fn[MAX_STATE] = 
    .handler = handler_state_0, ,
    .handler = handler_state_1, ,
    .handler = handler_state_2, ,
;

然后调用state_fn[state]->handler();

您可以选择从结构中添加参数。像这样:

struct state_fn 
    void (*handler)(void *data);
    void *data;

然后调用state_fn[state]->handler(state_fn[state]->data);

 .handler = handler_state_0, .data = "blabla" ,

如果一个函数处理程序可以服务于多个状态,这很方便。

【讨论】:

以上是关于带函数指针的状态机:如何设置函数指针?的主要内容,如果未能解决你的问题,请参考以下文章

状态机、子类和函数指针

涉及函数指针和状态机的代码解释

C#中调用dll,函数参数带指针,如何改写?

Qt带参数的信号,和指针函数和函数指针

带指针的函数

不带星号的函数指针参数