OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7591|回复: 8

关于状态机程序设计中函数指针结构体使用的疑惑

[复制链接]

30

主题

149

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
417
金钱
417
注册时间
2018-2-9
在线时间
117 小时
发表于 2022-2-7 15:24:33 | 显示全部楼层 |阅读模式
10金钱
最近看了一篇文章,是关于c语言设计模式--状态模式(状态机)https://www.eet-china.com/mp/a19504.html#:~:text=%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%20%28%E7%8A%B6%E6%80%81%E6%9C%BA%29%E6%98%AF%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E6%9C%80%E9%87%8D%E8%A6%81%E3%80%81%E6%9C%80%E6%A0%B8%E5%BF%83%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E4%B8%80%EF%BC%8C%E6%AF%AB%E4%B8%8D%E5%A4%B8%E5%BC%A0%E7%9A%84%E8%AF%B4%EF%BC%8C%E6%98%AF%E5%90%A6%E7%86%9F%E7%BB%83%E6%8E%8C%E6%8F%A1%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%BE%88%E5%A4%A7%E7%A8%8B%E5%BA%A6%E4%B8%8A%E7%9B%B4%E6%8E%A5%E5%86%B3%E5%AE%9A%E4%BA%86%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%B7%A5%E7%A8%8B%E5%B8%88%E7%9A%84%E4%BB%A3%E7%A0%81%E6%8E%8C%E6%8E%A7%E8%83%BD%E5%8A%9B%E3%80%82,%E5%9C%A8%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91%E9%87%8C%E9%9D%A2%EF%BC%8C%E5%87%A0%E4%B9%8E80%25%E4%BB%A5%E4%B8%8A%E7%9A%84%E7%A8%8B%E5%BA%8F%E9%83%BD%E6%9C%89%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%20%28%E7%8A%B6%E6%80%81%E6%9C%BA%29%E7%9A%84%E5%BD%B1%E5%AD%90%E3%80%82
关于最后的这几个结构体完全没有看懂,
State context = {
  onStop,
  onPlayOrPause
};

void onStop(State *pThis)
{
  pCurrentState->stop(pThis);
}

void onPlayOrPause(State *pThis)
{
  pCurrentState->palyOrPause(pThis);
}


/***********************************************
5、初始化系统当前状态指针,其实就是指定系统的起始状态
************************************************/

void init()
{
  pCurrentState = &IDLE;
}

/***********************************************
6、主程序通过上下文操作接口来控制系统当前状态的变化
************************************************/
void main()
{
  init();
  context.palyOrPause();//播放
  context.palyOrPause();//暂停
  context.palyOrPause();//播放
  context.stop();//停止
}



比如 void onPlayOrPause(State *pThis)
{
  pCurrentState->palyOrPause(pThis);
}这句里面的形参是个指向结构体的指针吧,但是也没见最后主函数里面函数有形参呀,有没有大佬答疑解惑一下

最佳答案

查看完整内容[请看2#楼]

你的意思是State context = { onStop, onPlayOrPause }; 这里里面关于onPlayOrPause 这个没有传入参数是吧,你看一下,context 这个不是函数,这个也是个变量来着,是State 类型的变量。 而State这个类型,是个结构体来着,你看一下定义 typedef struct State{ void (* stop)(); void (* palyOrPause)(); }State; 所以state这个结构体类型里面就是存了两个结构体元素,分别是两个函数指针,所以在context这个结 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

881

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4199
金钱
4199
注册时间
2019-9-4
在线时间
881 小时
发表于 2022-2-7 15:24:34 | 显示全部楼层
你的意思是State context = {
  onStop,
  onPlayOrPause
};  这里里面关于onPlayOrPause 这个没有传入参数是吧,你看一下,context 这个不是函数,这个也是个变量来着,是State 类型的变量。
而State这个类型,是个结构体来着,你看一下定义
typedef struct State{
  void (* stop)();
  void (* palyOrPause)();
}State;
所以state这个结构体类型里面就是存了两个结构体元素,分别是两个函数指针,所以在context这个结构体变量里面就只传入了函数名这个指针,并不需要传入参数,在具体使用的时候才需要传入参数,看了下帖子里面在main函数具体使用的时候没有传入参数,这里估计是写错了吧,编译应该会报错的。
回复

使用道具 举报

30

主题

149

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
417
金钱
417
注册时间
2018-2-9
在线时间
117 小时
 楼主| 发表于 2022-2-12 14:36:18 | 显示全部楼层
A571157242 发表于 2022-2-8 11:00
你的意思是State context = {
  onStop,
  onPlayOrPause

感谢回复,经过我试验,应该是原作者写错了,我把那两个形参删除之后程序也是正常的,结构体里的函数指针指向的就是没有形参的函数,所以这里自然就不应该有形参
回复

使用道具 举报

45

主题

267

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2018-6-24
在线时间
156 小时
发表于 2023-1-12 16:46:44 | 显示全部楼层
非常不错,看起来很实用,谢谢分享
回复

使用道具 举报

45

主题

267

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2018-6-24
在线时间
156 小时
发表于 2023-1-12 18:51:30 来自手机 | 显示全部楼层
看不懂state PLAY={ignor,startplay};赋值吗?
回复

使用道具 举报

45

主题

267

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2018-6-24
在线时间
156 小时
发表于 2023-1-12 18:57:19 来自手机 | 显示全部楼层
明白了,是定义PLAY的结构体
回复

使用道具 举报

45

主题

267

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2018-6-24
在线时间
156 小时
发表于 2023-1-12 19:13:21 来自手机 | 显示全部楼层
pThis是playOrPuase的PLAY或PAUSE这两个变量的值,知道是这样,这种代码很难理解
回复

使用道具 举报

30

主题

149

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
417
金钱
417
注册时间
2018-2-9
在线时间
117 小时
 楼主| 发表于 2023-1-12 20:59:08 | 显示全部楼层
wdmvw 发表于 2023-1-12 19:13
pThis是playOrPuase的PLAY或PAUSE这两个变量的值,知道是这样,这种代码很难理解

函数指针的结构体算是有点绕的概念了
回复

使用道具 举报

45

主题

267

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2018-6-24
在线时间
156 小时
发表于 2023-1-13 10:35:34 | 显示全部楼层
没有定义函数形参列表,后期调用不可以吗?
我全都给它附带上参数,结果也是可以的。
void onStop(State *pThis);
void onPlayOrPause(State *pThis);

State context = {
  onStop,
  onPlayOrPause
};

void onStop(State *pThis)
{
  pCurrentState->stop(pThis);
}

void onPlayOrPause(State *pThis)
{
  pCurrentState->palyOrPause(pThis);
}


/***********************************************
5、初始化系统当前状态指针,其实就是指定系统的起始状态
************************************************/

void init()
{
  pCurrentState = &IDLE;
}

/***********************************************
6、主程序通过上下文操作接口来控制系统当前状态的变化
************************************************/
int main()
{
  init();
  context.palyOrPause(*pCurrentState);//播放
  context.palyOrPause(*pCurrentState);//暂停
  context.palyOrPause(*pCurrentState);//播放
  context.stop(*pCurrentState);//停止
  return 0;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 19:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表