例如:
int getNext(int n) {
while (TRUE) {
n = n+1;
yield n;
}
}
int main() {
while (TRUE) {
int n = getNext(1);
if (n > 42)
break;
printf("%d\n",n);
}
}
这样上面的代码将打印从1到42的所有数字。
我想让yield
将getNext的地址更改为yield
之后的指令。但我无法弄清楚如何保存上下文(寄存器/变量),因为堆栈将由调用函数运行。
注意:
我意识到上面的代码可以通过静态变量轻松实现,但这不是重点。
答案 0 :(得分:12)
即使是在便携式C中,你也可以这样做。这是一个粗略的例子(gcc -Wall gen.c
):
#include <stdbool.h>
#include <stdio.h>
#include <setjmp.h>
#define YIELD(func, n) if (! setjmp(func##_gen_jmp)) { \
func##_ret = n; \
longjmp(func##_caller_jmp, 1); \
}
#define GENERATOR(ret, func, argt, argv) \
static jmp_buf func##_caller_jmp; \
static jmp_buf func##_gen_jmp; \
static bool func##_continue=false; \
static ret func##_ret; \
\
void func##__real(argt argv); \
\
ret func(argt argv) { \
if (!func##_continue) { \
func##_continue=true ; \
if (! setjmp(func##_caller_jmp)) { \
func##__real(argv); \
} else { \
return func##_ret; \
} \
} \
else { \
longjmp(func##_gen_jmp,1); \
} \
return 0; \
} \
void func##__real(argt argv)
GENERATOR(int, getNext, int, n) {
static int counter;
counter = n;
while (true) {
counter = counter+1;
YIELD(getNext, counter);
}
}
int main() {
while (true) {
int n = getNext(1);
if (n > 42)
break;
printf("%d\n",n);
}
return 0;
}
答案 1 :(得分:2)
您正在寻找的内容被称为“协同程序”,并且(至少不会失去一般性 - 请参阅有限情况下执行此方法的其他答案) portable C.有许多技巧可以伪造它们;请参阅http://en.wikipedia.org/wiki/Coroutine#Implementations_for_C了解几个。