2012-06-25 103 views
1

我试图在C中实现有限状态机,并且需要它非常快速。 所以我决定用函数指针为 “国”:有限状态机实现

void *state1(void){ /* function body here */ } 
void *state2(void){ /* ... */ } 
void *state3(void){ /* ... */ } 

然后,主FSM循环可以很简单:

void *(*fp)(void); 
fp = state1; 

while(fp) 
    fp = fp(); 

有一个问题:

1)它是可能避免在函数返回类型中使用void指针?理想情况下,状态函数应该有一些类型定义的类型,以确保在FSM中只能使用这种类型的函数。

2)在C语言中实现FSM的传统方法是使用enum进行状态和基于开关的调度器循环,因此与基于函数指针的实现相比,会有一个间接级别。
但我不确定,那里的指令缓存或分支预测有一些问题吗?换句话说,是否存在可以超越我的解决方案的实现?

谢谢。

+1

我有闻到微型优化吗?状态机需要运行几毫秒? –

+0

@Seva Alekseyev有些州比较大而且速度慢,但有些非常小而且简单。当FSM处于“大”状态之一时,性能并不重要,但小型状态必须尽可能快地执行。 –

+0

如果您希望速度更快,请使用单热编码状态机。你过早的优化不会很长。你最好编写可读,可维护和可扩展的代码。另外,对于C++ - http://www.boost.org/doc/libs/1_49_0/libs/statechart/doc/index.html – 2012-06-25 04:08:12

回答

3

要在C中创建一个像这样的递归类型定义,您需要在该行的某处使用struct,因为您无法“转发声明”typedefs。在循环

struct state { 
    struct state (*func)(void); 
}; 

然后:例如,你可以用一个struct中的函数指针

struct state state = { state1 }; 

while (state.func) { 
    state = state.func(); 
} 
0

1)typedef void(*state_fp)(void);

state_fp state1(void) { } 

2)取决于,小环与内置到函数的代码会比使函数调用更快。例如一个switch语句,其中每个状态都在switch语句中实现,但是,如果case语句过多,这将在函数调用下面退化

+0

这将需要在返回时进行强制转换,因为函数返回的类型不同作为指向函数本身的指针的类型(它比OP更好,至少你从一个函数指针类型转换到另一个函数指针类型,所以它是很好定义的)。 – caf

1

C中不可能声明一个返回指向函数的指针的函数属于自己的类型。而且,你不能使用void *,因为C不允许在函数和对象指针之间进行转换。相反,您可以使用:

typedef void (*generic_func_ptr)(void); 
typedef generic_func_ptr (*state_func_ptr)(void); 
generic_func_ptr state1(void), state2(void), state3(void); 
state_func_ptr fp; 

while(fp) 
    fp = (state_func_ptr)fp(); 

丑,但它的作品。相反,我会考虑使用switch语句。对于实现状态机来说它更加清洁。

3

在这里,你可能会发现你的问题的答案:http://code.google.com/p/fwprofile/

这是一个开放源代码版本(GNU GPLv3)采用C语言实现的 。该概念和实现非常适合在关键任务应用程序中使用 。有部署在工业 应用程序。