C99 goto label地址实现C语言协程
来源:互联网 发布:msa是什么软件啊 编辑:程序博客网 时间:2024/05/18 22:50
以前用C语言中的switch case实现过一个简单的协程,并应用到了实际的项目里。文章在这里,C语言实现协程,最近了解到C99中,goto语句可以跳转到一个变量里,变量保存的是label的地址。于是瞬间想到,这个可以替换协程实现中的switch case的机制。
首先,说明一下什么是goto到标签地址。
int main() { static void* p = &&label; goto *p; printf("before label\n"); label: printf("after label\n"); return 0;}
- &&label是语法,&&就是获得label的地址,并不是取地址在取地址。
- goto *p 就是跳转到p指针,所指向的地址。
- 如果p指向了的是不正确的地址,程序会运行时崩溃。
- label地址需要用void*指针才存放。
那么,现在我们看怎么用这个机制来实现协程。之前需要阅读,C语言实现协程,重复内容不再叙述。只贴出改造的的部分。
/** * Construct goto label with line number */#define _ACoroutineLabel(line) label##line#define ACoroutineLabel(line) _ACoroutineLabel(line)#define ACoroutineBegin() \ if (coroutine->step != NULL) \ { \ goto *coroutine->step; \ } \ coroutine->state = coroutine_state_running \#define ACoroutineEnd() \ coroutine->state = coroutine_state_finish#define ACoroutineYieldFrame(waitFrameCount) \ coroutine->waitValue = waitFrameCount; \ coroutine->curWaitValue = 0.0f; \ coroutine->waitType = coroutine_wait_frame; \ coroutine->step = &&ACoroutineLabel(__LINE__); \ return; \ ACoroutineLabel(__LINE__):#define ACoroutineYieldSecond(waitSecond) \ coroutine->waitValue = waitSecond; \ coroutine->curWaitValue = 0.0f; \ coroutine->waitType = coroutine_wait_second; \ coroutine->step = &&ACoroutineLabel(__LINE__); \ return; \ ACoroutineLabel(__LINE__):#define ACoroutineYieldCoroutine(waitCoroutine) \ coroutine->waitValue = 0.0f; \ coroutine->curWaitValue = 0.0f; \ coroutine->waitType = coroutine_wait_coroutine; \ AArrayListAdd((waitCoroutine)->waits, coroutine); \ coroutine->step = &&ACoroutineLabel(__LINE__); \ return; \ ACoroutineLabel(__LINE__):
- 首先,我们把coroutine->step改成void*类型,存储label标签地址。
- ACoroutineLabel 是为了展开__Line__定义,构造label + 行号的标签名称。
- 接下来就是,在每次进入协程函数的时候,直接goto到step存储的标签上。
- 没有了switch case,就避免了switch嵌套的可能性错误。并且提升了效率。
- 协程函数用使用的,中断宏定义,就是退出+打标签,下次goto到标签处继续运行。
最后,看看使用的样子。
static void LoadingRun(Coroutine* coroutine){ static int progress = 0;//-------------------------------------------------------------------------------------------------- ACoroutineBegin(); for (; progress < progressSize; progress++) { ACoroutineYieldFrame(0); } ACoroutineYieldSecond(1.0f); ACoroutineEnd();}static void OnReady(){ ACoroutine->StartCoroutine(LoadingRun);}
1 1
- C99 goto label地址实现C语言协程
- 「游戏引擎Mojoc」(7)C使用goto label地址实现协程
- c语言 c99 标准
- C语言goto关键字
- C语言goto语句
- C语言goto语句
- C语言goto!!!!!!!!!!!!
- c语言 goto语句
- C语言 goto语句
- C语言中的goto
- C语言goto语句
- c语言 goto语句
- C语言goto语句
- C语言goto 语句
- c语言,goto用法,goto最强使用方法
- C语言用 if + goto 实现while功能
- C语言 C99新增关键字
- C语言 goto 使用实例
- 24点游戏
- RecycleView
- 练习使用innerHTML和outerHTML追加元素
- Androind 对话框 1
- Gradle 依赖管理
- C99 goto label地址实现C语言协程
- 二分查找
- android 将布局延伸到状态栏
- 推荐一份 Google 面试指南
- js中var的重复声明
- MyBatis实现单表增删改查(CURD)--修改
- android系统源码之 系统应用安装过程(下)
- ajax的使用
- win7新建文本文档快捷键