【赤石C++】使用宏魔法在 C 语言中实现协程

协程

协程(Coroutine) 可以看作是“可暂停和恢复的函数”。与普通函数只能“调用-返回”一次不同,协程可以在执行过程中多次暂停(yield)并交出控制权,之后又能从上次暂停的地方继续执行

比如:

1
2
3
4
5
6
7
8
def my_coroutine():
for i in range(3):
yield i # 暂停并返回 i

gen = my_coroutine()
print(next(gen)) # 输出 0
print(next(gen)) # 输出 1
print(next(gen)) # 输出 2

每次调用next(),协程就从上次yield的地方继续执行

C 语言实现协程

赤过“达夫设备”这篇文章的都知道,switch 语句的 case 标签可以出现在 switch 内部任意位置,甚至嵌套在另一个循环里

<此处插入公众号超链接>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

#define crBegin static int state = 0; switch (state) { case 0:
#define crReturn(x) do { state = __LINE__; return x; case __LINE__:; } while (0)
#define crFinish }

int my_coroutine() {
static int i;

crBegin;
for (i = 0; i < 3; ++i) {
crReturn(i);
}
crFinish;
}

int main() {
std::cout << my_coroutine() << std::endl; // 输出 0
std::cout << my_coroutine() << std::endl; // 输出 1
std::cout << my_coroutine() << std::endl; // 输出 2
}

(如果你使用 MSVC,这段代码可能需要 Release 模式才能编译)

乍一看有点魔法,我们不妨先手动将宏展开再进行分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

int my_coroutine_no_macro() {
static int i;

/* --- crBegin; 展开开始 --- */
static int state = 0;
switch (state) {
case 0:;
/* --- crBegin; 展开结束 --- */

for (i = 0; i < 3; ++i) {

/* --- crReturn(i); 展开开始 --- */
do {
state = 23; // 假设这行是第 23 行(__LINE__ 宏展开结果)
return i;
case 23:; // 这一行也是 23,我为了方便阅读手动加上回车了
} while (0);
/* --- crReturn(i); 展开结束 --- */

}

/* --- crFinish; 展开开始 --- */
};
/* --- crFinish; 展开开始 --- */
}

执行流程:

首次调用时

  • 初始时 state = 0switch 进入 case 0 分支
  • case 0 后面跟的是一条空语句(一个分号),所以 fall-throughfor 循环起始处
1
2
3
4
5
6
7
case 0:;
/* fall through */

// 穿透到 for 循环处
for(i = 0; i < 3; ++i)

/* ...... */
  • do { ... } while(0) 不需要特别分析,这个是常用的编程技巧,本文不会涉及
  • 进入 for 循环后,将 state 设置为 23,并返回初始 i = 0

再次调用时

  • 由于 state = 23switch 语句进入 case 23 分支
  • 同样的,case 23 后面跟的也是一条空语句,所以fall-throughfor 循环末尾,并进行条件判断
  • 条件判断成立时,for 循环跳转到开头再次执行,由于 i 是静态变量,保存了上一次调用的状态,所以返回 i = 1

参考

https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html (顺带一提,这位大神还是 PuTTY 的开发者)

https://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B


【赤石C++】使用宏魔法在 C 语言中实现协程
https://crackme.net/articles/coroutine/
作者
Brassinolide
发布于
2026年2月13日
许可协议