C FSM状态的一种热编码

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)

Ste*_*314 6

从一个快速的谷歌,"一个热编码"意味着每个有效的代码恰好有一个位设置,这似乎是你正在做的.搜索结果表明这是一种硬件设计模式.

我能想到的缺点是......

  1. 正如你的建议,你大大限制了有效代码的数量 - 对于32位,你最多有32个代码/状态而不是超过40亿.

  2. 它对于查找表来说并不理想,查找表是switch语句的常见实现.通常有一个内在可用来确定哪个是最低位集,但我不打赌自动使用它的编译器.

但是,如果国家数量很少,这些都不是大问题.

那么,IMO的问题是,证明成本合理是否有优势.它不需要是一个巨大的优势,但必须有某种观点.

我能想出的最好的是,你可以使用位招数来指定状态集合,所以你可以测试当前状态是否是在给定的设置有效-如果你有一些动作需要在美国做(1<<0)(1<<3),为例如,你可以测试if (state & 0x9).