还是上次在comp.lang.c++上看到的那个关于用C++写出仿 BASIC 的代码的话题,后来竟然又出现一段模拟 GOSUB 和 RETURN 的代码,让我看后几乎瞠目结舌,于是再转过来续一下(这段代码用了gcc的一个扩展关键词__label__):

cpp
 1#include <list>
 2#include <stdio.h>
 3
 4std::list<void*> GosubStack;
 5void B_ERROR(int e) { throw e; } // for reporting errors
 6
 7#define B_GOSUB(label) \
 8{ __label__ gosub_return; GosubStack.push_back(&&gosub_return); \
 9    goto label; gosub_return:; }
10#define B_RETURN() \
11{ if (GosubStack.empty()) B_ERROR(2);/* RETURN WITHOUT GOSUB*/ \
12    else { void* ret = GosubStack.back(); GosubStack.pop_back(); \
13        goto *ret; } }
14#define B_RETURN_TO(label) \
15{ if (GosubStack.empty()) B_ERROR(2);/* RETURN WITHOUT GOSUB*/ \
16    else { GosubStack.pop_back(); goto label; } }
17
18int main()
19{
20    B_GOSUB(root);
21    puts("0");
22    goto owa;
23root:
24    puts("1");
25    B_GOSUB(beg);
26    puts("2");
27beg:
28    puts("3");
29    B_GOSUB(wan);
30    puts("4");
31    B_GOSUB(too);
32    puts("5");
33wan:
34    puts("6");
35    B_RETURN();
36too:
37    puts("7");
38    B_RETURN_TO(wan);
39owa:
40    return 0;
41}

程序输出结果: 1 3 6 4 7 6 2 3 6 4 7 6 0.

注:特别是其中还模仿了一个Basic中超级 spaghetti 的语句:B_RETURN_TO,对应Basic里的 return label语句(在Basic里,竟然可以在子程序里面返回到指定的行号,而不一定是调用子程序的地方!)

评论(备份自LiveSpace):

  • 2007-10-07 - 忘: 不懂,不過踩個腳印。氣死我了,紫光輸入法被大瘋,只能輸入繁體了,我現在想掐他的脖子。