Plo*_*uff 3 c state state-machine
基本上,我只想知道手动热编码C FSM的状态是否是个好主意.我实现了这个来编写一个简单的状态转换验证器:
typedef enum
{
FSM_State1 = (1 << 0),
FSM_State2 = (1 << 1),
FSM_State3 = (1 << 2),
FSM_StateError = (1 << 3)
} states_t;
Run Code Online (Sandbox Code Playgroud)
然后验证:
states_t nextState, requestedState;
uint32_t validDestStates = 0;
// Compute requested state
requestedState = FSM_State1;
// Define valid transitions
validDestStates |= FSM_State2;
validDestStates |= FSM_State3;
// Check transition
if (validDestStates & requestedState)
{
// Valid transition
nextState = requestedState;
}
else
{
// Illegal transition
nextState = FSM_StateError;
}
Run Code Online (Sandbox Code Playgroud)
我知道我被限制为可以使用的最大整数大小.但我没有那么多州.所以这不是问题
有没有比这种编码更好的东西?有什么缺点我还没看到吗?
谢谢你的帮助!
编辑:根据user3386109评论更改验证测试
所以最后我就是这样做的:
1/State enum是一个"经典"枚举:
typedef enum
{
FSM_State1,
FSM_State2,
FSM_State3,
FSM_StateError
} states_t;
Run Code Online (Sandbox Code Playgroud)
2 /有效转换的位字段:
struct s_fsm_stateValidation
{
bool State1IsValid: 1;
bool State2Valid: 1;
bool State3IsValid: 1;
bool StateErrorIsValid: 1;
/// Reserved space for 32bit reserved in the union
uint32_t reserved: 28;
};
Run Code Online (Sandbox Code Playgroud)
3 /创建验证联合
typedef union FSM_stateValidation_u
{
/// The bit field of critical system errors
struct s_fsm_stateValidation state;
/// Access the bit field as a whole
uint32_t all;
} u_FSM_stateValidation;
Run Code Online (Sandbox Code Playgroud)
4 /我改变了验证:
u_FSM_stateValidation validDestStates;
// Set valid states
validDestStates.state.State1 = true;
// Compute requestedState
requestedState = FSM_State2;
if ((validDestStates.all & ((uint32_t) (1 << requestedState)) ))
{
// Next state is legal
return requestedState;
}
else
{
return FSM_StateError;
}
Run Code Online (Sandbox Code Playgroud)
从一个快速的谷歌,"一个热编码"意味着每个有效的代码恰好有一个位设置,这似乎是你正在做的.搜索结果表明这是一种硬件设计模式.
我能想到的缺点是......
正如你的建议,你大大限制了有效代码的数量 - 对于32位,你最多有32个代码/状态而不是超过40亿.
它对于查找表来说并不理想,查找表是switch语句的常见实现.通常有一个内在可用来确定哪个是最低位集,但我不打赌自动使用它的编译器.
但是,如果国家数量很少,这些都不是大问题.
那么,IMO的问题是,证明成本合理是否有优势.它不需要是一个巨大的优势,但必须有某种观点.
我能想出的最好的是,你可以使用位招数来指定状态集合,所以你可以测试当前状态是否是在给定的设置有效-如果你有一些动作需要在美国做(1<<0)和(1<<3),为例如,你可以测试if (state & 0x9).