我正在尝试用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 指针?理想情况下,状态函数应该具有某种 typedef'ed 类型,以确保在 FSM 中仅使用此类型的函数。
2)在C中实现FSM的传统方法是使用枚举作为状态和基于交换机的调度程序循环,因此与基于函数指针的实现相比,将有一个间接级别。
但我不确定,指令缓存或分支预测的一些问题是否有一席之地?换句话说,是否存在可以胜过我的解决方案的实现?
谢谢。
要在 C 中创建这样的递归类型定义,您需要在沿线的某处使用struct
,因为您不能"正向声明"typedefs。 例如,您可以将函数指针包装在struct
中:
struct state {
struct state (*func)(void);
};
然后在循环中:
struct state state = { state1 };
while (state.func) {
state = state.func();
}
在这里,您可能会找到问题的答案:http://code.google.com/p/fwprofile/
它是实现的状态机的开源版本(GNU GPLv3)在C中。该概念和实现非常适合在任务关键型应用程序。在工业领域有部署应用。
在 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 语句。对于实现状态机来说,它要干净得多。
1) typedef void(*state_fp)(void);
state_fp state1(void) { }
2)取决于,将代码内置到函数中的小循环将比进行函数调用更快。 例如,一个switch语句,其中每个状态都在switch语句中实现,但是,如果案例语句太多,这将降低下面的函数调用
如果其他人想使用 fsm的免费框架,请查看 http://www.block-net.de/Programmierung/cpp/fsm/fsm.html有一个 C 和 C++ 有限状态机框架,包括带有 PlantUML 的状态图生成器。