在阅读Erts的代码的时候,尤其是在process_main这个函数的时候。看到一个奇怪的宏叫做NO_JUMP_TABLE,里面定义的数组opcodes[] = { DEFINE_OPCODES };其中DEFINE_OPCODES的定义是以&&开头的标签。
如下面的代码例子:
#include<string.h> #include<stdlib.h> #include<stdio.h> #define LabelAddr(Addr) &&Addr int main(){ void* opcodes[] = {&&lb_catch_end_y}; opcodes[0] = LabelAddr(lb_catch_end_y); free(opcodes); return 0; lb_catch_end_y: printf("Never seen this \r\n"); return 1; }
其中lb_catch_end_y是goto标签,可以使用&&lb_catch_end_y来获得goto标签的地址。通过不断添加goto标签的地址到opcodes数组中,我们通过直接goto *opcodes[0]来进行跳转,当我们在运行时更换opcodes[0]中的地址,我们就会很方便的在这个函数内跳转来跳转去的,并且可以使用整个函数内所有的局部变量。
那么这东西可以干什么事情呢,通过这东西,我们就可以用C语言构造出高级语言所具有的尾递归。或者使用这个东西来构造自定义的执行流程,就像Erts的process_main那样的虚拟指令解释器。
原文:http://my.oschina.net/u/236698/blog/379368