- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
基本上,我只想知道手动对 C FSM 的状态进行热编码是否是个好主意。我实现了它来编写一个简单的状态转换验证器:
typedef enum
{
FSM_State1 = (1 << 0),
FSM_State2 = (1 << 1),
FSM_State3 = (1 << 2),
FSM_StateError = (1 << 3)
} states_t;
然后验证:
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;
}
我知道我受限于我可以使用的最大整数大小。但是我没有那么多状态。所以这不是问题
有比这种编码更好的东西吗?是否有一些我还没有看到的缺点?
感谢您的帮助!
编辑:根据 user3386109 评论更改了验证测试
最后就是我所做的:
1/状态枚举是一个“经典”枚举:
typedef enum
{
FSM_State1,
FSM_State2,
FSM_State3,
FSM_StateError
} states_t;
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;
};
3/为验证创建一个 union
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;
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;
}
最佳答案
从快速 Google 中,“一个热编码”意味着每个有效代码都恰好设置了一位,这似乎就是您正在做的。搜索结果表明这是一种硬件设计模式。
我能想到的缺点是...
正如您所建议的,您极大地限制了有效代码的数量 - 对于 32 位,您最多有 32 个代码/状态,而不是超过 40 亿。
它不是查找表的理想选择,查找表是 switch
的常见实现。声明。通常有一个内部函数可用于确定哪个是最低位集,但我不会打赌编译器会自动使用它。
不过,只要州的数量很少,这些都不是大问题。
那么,IMO 的问题是,是否有优势证明该成本是合理的。它不需要是一个巨大的优势,但必须有某种意义。
我能想到的最好办法是你可以使用按位技巧来指定状态集,这样你就可以有效地测试当前状态是否在给定的集合中——如果你有一些需要在状态中完成的 Action (1<<0)
和 (1<<3)
,例如,您可以测试 if (state & 0x9)
.
关于c - C FSM 状态的一种热编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32220507/
我想要类似于以下伪代码的东西: while input is not None and timer = 5: print "took too long" else: print inp
如何将 MainEngine Observable 转换为 Cold?来自这个例子: public IObservable MainEngine { get
自从手表被发明以来,表盘的方圆之争就始终没有停下来过,在漫长的岁月中,无论是方形还是圆形表盘,人们都为其寻找到足够多的设计元素,让其肆意成长,这种生机与活力后来也延续到了智能手表上,在2014年,这
我正在学习 CUDA,试图解决一些标准问题。例如,我正在使用以下代码求解二维扩散方程。但我的结果与标准结果不同,我无法弄清楚。 //kernel definition __global__ void
我的 Web 应用程序使用 native dll 来实现其部分功能(其位置在 PATH 中提供)。一切正常,直到我对 WAR 进行更改并且 JBoss 热部署此 WAR。此时dll已经找不到了,需要手
我看到这个问题here 。这是关于实现每个发出的项目的延迟。这是根据accepted answer如何实现的: Observable.zip(Observable.range(1, 5) .g
我最近一直在进行冷迁移...这意味着我无法在进行迁移时从应用程序级别读取/写入数据库(维护页面)。 这样就不会因为更改结构而发生错误,而且如果负载很大,我也不希望 mysql 在迁移过程中崩溃。 我的
我是一名优秀的程序员,十分优秀!